diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index eab7626fa1..f36b3e132a 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -1701,7 +1701,15 @@ connections; validating the port is therefore unlikely to be successful. If the client has a token received in a NEW_TOKEN frame on a previous connection to what it believes to be the same server, it SHOULD include that value in the Token field of its Initial packet. Including a token might allow the server to -validate the client address without an additional round trip. +validate the client address without an additional round trip. When using a +NEW_TOKEN token for establishing a new connection, the client MUST construct its +long header packets by using the seeds that were provided alongside that token +(see {{seeding}}). When the client receives a Version Negotiation packet in +response containing the QUIC version from which the client obtained the +NEW_TOKEN token, the client MAY restart the connection establishment process +using the default seeds of that QUIC version. When doing so, the client MUST +offer the same NEW_TOKEN token. The client MUST discard Version Negotiation +packets that do not contain the original version. A token allows a server to correlate activity between the connection where the token was issued and any connection where it is used. Clients that want to @@ -2721,6 +2729,115 @@ between endpoints. Application protocols SHOULD define rules for handling streams that are prematurely cancelled by either endpoint. +# Seeding {#seeding} + +In order to avoid ossification of the cleartext and obfuscated fields of QUIC +packets, a server can announce a set of alternative initial values to be used, +which is comprised of: + +* Version number; a 32-bit unsigned number that is to be presented on wire in + place of the version number specified in this document. This value MUST NOT + be a reserved version ({{versions}}). + +* Packet type modifier; a two-bit value that obfuscates the Long Packet Type of + a long header packet ({{long-header}}). The long packet type bits of a long + header packet is encoded as an bit-wise exclusive or (XOR) of the packet type + modifier and the type numbers defined in {{long-packet-types}}. + +* Initial salt; a 16-byte binary blob that is to be used in place of the initial + salt defined in section 5.2 of {{QUIC-TLS}}. + +A server advertises these seeds using a NEW_TOKEN frame {{frame-new-token}}. +The token MUST permit the server to recover these seeds. This property can be +achieved for example by embedding these seeds in the encrypted token. + +For the non-default seeds to work, all the servers within the scope of a +NEW_TOKEN token are required to have a shared knowledge of those seeds being +issued and / or how they can be recovered from the tokens. Certain server +deployments might have difficulty in meeting such a requirement. + +A server (or a set of servers) that cannot satisfy this requirement can stick to +using the default values by consistently advertising the default version number, +default initial salt, and a packet type modifier of zero in the NEW_TOKEN frames +it sends. + +The rest of this section applies to the servers that advertise non-default +values as their seeds. + + +## Server Behavior + +Typically, a server that advertises the alternative seeds would act in the +following steps: + +* The server pre-allocates a set of unused version numbers as the alternative + version numbers, associating each of those version numbers with a packet type + modifier chosen at random. + +* When issuing a NEW_TOKEN token, the server generates the alternative initial + salt using a cryptographically secure pseudo-random number generator. Then it + builds a token that embeds the alternative seeds including the initial salt + being generated. The token will be encrypted using a key known only to the + server, thereby conforming to the requirements in {{validate-future}}. After + that, the server sends a NEW_TOKEN frame that contains the generated token and + the seeds that have been embedded into that token. + +* When the client reconnects to the server by using the provided token and the + seeds, the server first checks if the version number field of the incoming + packet contains one of the alternative version numbers it advertises, then if + that is the case, applies the corresponding packet type modifier to recover + the correct packet type. If the recovered packet type is an Initial packet + and that packet contains a NEW_TOKEN token, the server decrypts the embedded + token and recovers the initial salt, uses that to decrypt the payload of the + Initial packet. + +* When sending a Retry in response to an Initial packet carrying an alternative + version number, the server embeds the NEW_TOKEN token found in the Initial + packet within the retry token it issues. Once the server receives a response + from the client carrying that retry token and the path is validated, it + decrypts the NEW_TOKEN token embedded within the retry token to recover the + alternative initial salt that is to be used for unprotecting the packet + payload. + +Instead of associating a new alternative initial salt with every NEW_TOKEN +token, a server might map a fixed salt to each of the alternative version +numbers it issues. Such design is not recommended, as an active attacker might +build a list of known alternative version numbers and their initial salts and +use that list to decrypt the payload of Initial packets using those alternative +version numbers. But still, having a set of version numbers and initial salts +used concurrently is considered better than just using the default values of +QUIC in terms of preventing ossification. + +When sending a Retry packet in response to an Initial packet, the server MUST +build the retry token in such way that the seeds that were associated with the +original token can be recovered from the retry token (in case the original token +was valid), or embed in the retry token that the original token was invalid. + +When the server receives an Initial packet using an alternative version number +but is incapable of determining the alternative initial salt from the token +being associated, it MAY send a Version Negotiation packet that instructs the +client to use the default version. + +In order to prevent corrupt Initial packets being misidentified as the client +using an unusable token, a server MUST issue the tokens in such way that their +accidental corruption can be detected, at least until those tokens expire (see +{{frame-new-token}}). One reasonable way of accomplishing this requirement is +to embed a checksum obtained from an unkeyed hash function (e.g., SHA-256; +{{?RFC6234}}) to every token. + +When the server receives an Initial packet containing a valid token, and the +value of the version number field of that Initial packet does not match the +version number recovered from the token, the server MUST close the connection +with a VERSION_NEGOTIATION_ERROR. + + +## Distributing the Seeds + +This specification defines how the seeds are used as well as how they are +advertised using a NEW_TOKEN frame. Other specifications MAY define other +methods for distributing or deducing these seeds. + + # Packets and Frames {#packets-frames} QUIC endpoints communicate by exchanging packets. Packets have confidentiality @@ -4962,6 +5079,20 @@ The NEW_TOKEN frame is as follows: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Lifetime (i) ... ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Seeded Version Number (32) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +|R R R R R R|PTM| ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| | ++ + +| | ++ Seeded Initial Salt (128) + +| | ++ + +| | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Token Length (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Token (*) ... @@ -4970,6 +5101,30 @@ The NEW_TOKEN frame is as follows: NEW_TOKEN frames contain the following fields: +Lifetime: + +: Indicates the lifetime of the values contained in this frame in milliseconds. + An endpoint MUST NOT use the values provided by this frame once the time that + has elapsed since receipt becomes greater than the value of this field. + +Seeded Version Number: + +: The version number to be used alongside the token (see {{seeding}}). + +Reserved (R): + +: Reserved bits. These bits MUST be set to zero. An endpoint MUST treat + the receipt of a NEW_TOKEN frame carrying a non-zero reserved bit as a + connection error of type FRAME_ENCODING_ERROR. + +Packet Type Modifier (PTM): + +: The packet type modifier to be used alongside the token. + +Seeded Initial Salt: + +: The initial salt to be used to be used alongide the token. + Token Length: : A variable-length integer specifying the length of the token in bytes. @@ -5582,6 +5737,12 @@ TRANSPORT_PARAMETER_ERROR (0x8): an invalid value, was absent even though it is mandatory, was present though it is forbidden, or is otherwise in error. +VERSION_NEGOTIATION_ERROR (0x9): + +: An endpoint received a packet with an unexpected version. This error code + indicates a potential version downgrade attack. + + PROTOCOL_VIOLATION (0xA): : An endpoint detected an error with protocol compliance that was not covered by