diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index 509b7b27b8..800a1a7d74 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -716,7 +716,7 @@ respectively). Using these labels provides key separation between QUIC and TLS, see {{key-diversity}}. The HKDF-Expand-Label function is also used to derive the initial secrets (see -{{initial-secrets}}) and to derive a packet number protection key (the "quic pn" +{{initial-secrets}}) and to derive a packet number protection key (the "quic hp" label, see {{pn-encrypt}}). @@ -769,10 +769,9 @@ used for QUIC packet protection is the AEAD that is negotiated for use with the TLS connection. For example, if TLS is using the TLS_AES_128_GCM_SHA256, the AEAD_AES_128_GCM function is used. -QUIC packets are protected prior to applying packet number protection -({{pn-encrypt}}). The unprotected packet number is part of the associated data -(A). When removing packet protection, an endpoint first removes the protection -from the packet number. +Packets are protected prior to applying header protection ({{header-protect}}). +The unprotected packet header is part of the associated data (A). When removing +packet protection, an endpoint first removes the header protection. All QUIC packets other than Version Negotiation and Retry packets are protected with an AEAD algorithm {{!AEAD}}. Prior to establishing a shared secret, packets @@ -806,26 +805,113 @@ packet number limit. An endpoint MUST initiate a key update ({{key-update}}) prior to exceeding any limit set for the AEAD that is in use. -## Packet Number Protection {#pn-encrypt} +## Header Protection {#header-protect} -QUIC packet numbers are protected using a key that is derived from the current -set of secrets. The key derived using the "quic pn" label is used to protect -the packet number from casual observation. The packet number protection -algorithm depends on the negotiated AEAD. +Parts of QUIC packet headers, in particular the Packet Number field, are +protected using a key that is derived separate to the packet protection key and +IV. The key derived using the "quic hp" label is used to provide +confidentiality protection for those fields that are not exposed to on-path +elements. -Packet number protection is applied after packet protection is applied (see -{{aead}}). The ciphertext of the packet is sampled and used as input to an -encryption algorithm. +This protection applies to the least-significant bits of the first byte, plus +the Packet Number field. The four least-significant bits of the first byte are +protected for packets with long headers; the five least significant bits of the +first byte are protected for packets with short headers. For both header forms, +this covers the reserved bits and the Packet Number Length field; the Key Phase +bit is also protected for packets with a short header. -In sampling the packet ciphertext, the packet number length is assumed to be 4 -bytes (its maximum possible encoded length), unless there is insufficient space -in the packet for sampling. The sampled ciphertext starts after allowing for a -4 byte packet number unless this would cause the sample to extend past the end -of the packet. If the sample would extend past the end of the packet, the end -of the packet is sampled. +This process does not apply to Retry or Version Negotiation packets, which do +not contain a protected payload or any of the fields that are protected by this +process. -For example, the sampled ciphertext for a packet with a short header can be -determined by: + +### Header Protection Application + +Header protection is applied after packet protection is applied (see {{aead}}). +The ciphertext of the packet is sampled and used as input to an encryption +algorithm. The algorithm used depends on the negotiated AEAD. + +The output of this algorithm is a 5 byte mask which is applied to the protected +header fields using exclusive OR. The least significant bits of the first byte +of the packet are masked by the least significant bits of the first mask byte, +and the packet number is masked with the remaining bytes. Any unused bytes of +mask that might result from a shorter packet number encoding are unused. + +{{pseudo-hp}} shows a sample algorithm for applying header protection. Removing +header protection only differs in the order in which the packet number length +(pn_length) is determined. + +~~~ +mask = header_protection(hp_key, sample) + +pn_length = (packet[0] & 0x03) + 1 +if (packet[0] & 0x80) == 0x80: + # Long header: 4 bits masked + packet[0] ^= mask[0] & 0x0f +else: + # Short header: 5 bits masked + packet[0] ^= mask[0] & 0x1f + +# pn_offset is the start of the Packet Number field. +packet[pn_offset:pn_offset+pn_length] ^= mask[1:1+pn_length] +~~~ +{: #pseudo-hp title="Header Protection Pseudocode"} + +{{fig-sample}} shows the protected fields of long and short headers marked with +an E. {{fig-sample}} also shows the sampled fields. + +~~~ +Long Header: ++-+-+-+-+-+-+-+-+ +|1|1|T T|E E E E| ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Version -> Length Fields ... ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +Short Header: ++-+-+-+-+-+-+-+-+ +|0|1|S|E E E E E| ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Destination Connection ID (0/32..144) ... ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +Common Fields: ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +|E E E E E E E E E Packet Number (8/16/24/32) E E E E E E E E... ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| [Protected Payload (8/16/24)] ... ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Sampled part of Protected Payload (128) ... ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Protected Payload Remainder (*) ... ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +~~~ +{: #fig-sample title="Header Protection and Ciphertext Sample"} + +Before a TLS ciphersuite can be used with QUIC, a header protection algorithm +MUST be specified for the AEAD used with that ciphersuite. This document +defines algorithms for AEAD_AES_128_GCM, AEAD_AES_128_CCM, AEAD_AES_256_GCM, +AEAD_AES_256_CCM (all AES AEADs are defined in {{!AEAD=RFC5116}}), and +AEAD_CHACHA20_POLY1305 {{!CHACHA=RFC8439}}. Prior to TLS selecting a +ciphersuite, AES header protection is used ({{hp-aes}}), matching the +AEAD_AES_128_GCM packet protection. + + +### Header Protection Sample {#hp-sample} + +The header protection algorithm uses both the header protection key and a sample +of the ciphertext from the packet Payload field. + +The same number of bytes are always sampled, but an allowance needs to be made +for the endpoint removing protection, which will not know the length of the +Packet Number field. In sampling the packet ciphertext, the Packet Number field +is assumed to be 4 bytes long (its maximum possible encoded length), unless +there is insufficient space in the packet for a complete sample. The starting +offset for the sample is set to 4 bytes after the start of the Packet Number +field, then is reduced until there are enough bytes to sample. + +The sampled ciphertext for a packet with a short header can be determined by the +following pseudocode: ~~~ sample_offset = 1 + len(connection_id) + 4 @@ -835,6 +921,12 @@ if sample_offset + sample_length > packet_length then sample = packet[sample_offset..sample_offset+sample_length] ~~~ +For example, for a packet with a short header, an 8 byte connection ID, and +protected with AEAD_AES_128_GCM, the sample takes bytes 13 to 28 inclusive +(using zero-based indexing) as long as the packet is at least 29 bytes long. +The shortest packet that can be produced with this configuration is 27 bytes +long, in which case bytes 11 to 26 are sampled. + A packet with a long header is sampled in the same way, noting that multiple QUIC packets might be included in the same UDP datagram and that each one is handled separately. @@ -846,57 +938,51 @@ sample_offset = 6 + len(destination_connection_id) + if packet_type == Initial: sample_offset += len(token_length) + len(token) -~~~ -To ensure that this process does not sample the packet number, packet number -protection algorithms MUST NOT sample more ciphertext than the minimum expansion -of the corresponding AEAD. - -Packet number protection is applied to the packet number encoded as described in -Section 17.1 of {{QUIC-TRANSPORT}}. Since the length of the packet number is -stored in the first byte of the encoded packet number, it may be necessary to -progressively decrypt the packet number. +if sample_offset + sample_length > packet_length then + sample_offset = packet_length - sample_length +sample = packet[sample_offset..sample_offset+sample_length] +~~~ -Before a TLS ciphersuite can be used with QUIC, a packet protection algorithm -MUST be specifed for the AEAD used with that ciphersuite. This document defines -algorithms for AEAD_AES_128_GCM, AEAD_AES_128_CCM, AEAD_AES_256_GCM, -AEAD_AES_256_CCM (all AES AEADs are defined in {{!AEAD=RFC5116}}), and -AEAD_CHACHA20_POLY1305 ({{!CHACHA=RFC8439}}). +To ensure that this process does not sample the packet number, header protection +algorithms MUST NOT require a sample size larger than the minimum expansion of +the corresponding AEAD. -### AES-Based Packet Number Protection +### AES-Based Header Protection {#hp-aes} This section defines the packet protection algorithm for AEAD_AES_128_GCM, AEAD_AES_128_CCM, AEAD_AES_256_GCM, and AEAD_AES_256_CCM. AEAD_AES_128_GCM and -AEAD_AES_128_CCM use 128-bit AES {{!AES=DOI.10.6028/NIST.FIPS.197}} in counter -(CTR) mode. AEAD_AES_256_GCM, and AEAD_AES_256_CCM use 256-bit AES in CTR mode. +AEAD_AES_128_CCM use 128-bit AES {{!AES=DOI.10.6028/NIST.FIPS.197}} in +electronic code-book (ECB) mode. AEAD_AES_256_GCM, and AEAD_AES_256_CCM use +256-bit AES in ECB mode. This algorithm samples 16 bytes from the packet ciphertext. This value is used -as the counter input to AES-CTR. +as the counter input to AES-ECB. In pseudocode: ~~~ -encrypted_pn = AES-CTR(pn_key, sample, packet_number) +mask = AES-ECB(pn_key, sample) ~~~ -### ChaCha20-Based Packet Number Protection +### ChaCha20-Based Header Protection {#hp-chacha} -When AEAD_CHACHA20_POLY1305 is in use, packet number protection uses the raw -ChaCha20 function as defined in Section 2.4 of {{!CHACHA}}. This uses a 256-bit -key and 16 bytes sampled from the packet protection output. +When AEAD_CHACHA20_POLY1305 is in use, header protection uses the raw ChaCha20 +function as defined in Section 2.4 of {{!CHACHA}}. This uses a 256-bit key and +16 bytes sampled from the packet protection output. The first 4 bytes of the sampled ciphertext are interpreted as a 32-bit number in little-endian order and are used as the block count. The remaining 12 bytes are interpreted as three concatenated 32-bit numbers in little-endian order and used as the nonce. -The encoded packet number is then encrypted with ChaCha20 directly. In +The encryption mask is produced by invoking ChaCha20 to protect 5 zero bytes. In pseudocode: ~~~ counter = DecodeLE(sample[0..3]) nonce = DecodeLE(sample[4..7], sample[8..11], sample[12..15]) -encrypted_pn = ChaCha20(pn_key, counter, nonce, packet_number) +mask = ChaCha20(pn_key, counter, nonce, {0,0,0,0,0}) ~~~ @@ -1180,48 +1266,47 @@ SHOULD track redundant packets and treat excessive volumes of any non-productive packets as indicative of an attack. -## Packet Number Protection Analysis {#pn-encrypt-analysis} +## Header Protection Analysis {#pn-encrypt-analysis} -Packet number protection relies on the packet protection AEAD being a -pseudorandom function (PRF), which is not a property that AEAD algorithms +Header protection relies on the packet protection AEAD being a pseudorandom +function (PRF), which is not a property that AEAD algorithms guarantee. Therefore, no strong assurances about the general security of this mechanism can be shown in the general case. The AEAD algorithms described in this document are assumed to be PRFs. -The packet number protection algorithms defined in this document take the -form: +The header protection algorithms defined in this document take the form: ~~~ -encrypted_pn = packet_number XOR PRF(pn_key, sample) +protected_field = field XOR PRF(pn_key, sample) ~~~ This construction is secure against chosen plaintext attacks (IND-CPA) {{IMC}}. Use of the same key and ciphertext sample more than once risks compromising -packet number protection. Protecting two different packet numbers with the same -key and ciphertext sample reveals the exclusive OR of those packet numbers. -Assuming that the AEAD acts as a PRF, if L bits are sampled, the odds of two -ciphertext samples being identical approach 2^(-L/2), that is, the birthday -bound. For the algorithms described in this document, that probability is one in -2^64. +header protection. Protecting two different headers with the same key and +ciphertext sample reveals the exclusive OR of the protected fields. Assuming +that the AEAD acts as a PRF, if L bits are sampled, the odds of two ciphertext +samples being identical approach 2^(-L/2), that is, the birthday bound. For the +algorithms described in this document, that probability is one in 2^64. Note: : In some cases, inputs shorter than the full size required by the packet protection algorithm might be used. -To prevent an attacker from modifying packet numbers, values of packet numbers -are transitively authenticated using packet protection; packet numbers are part -of the authenticated additional data. A falsified or modified packet number can -only be detected once the packet protection is removed. +To prevent an attacker from modifying packet headers, the header is transitively +authenticated using packet protection; the entire packet header is part of the +authenticated additional data. Protected fields that are falsified or modified +can only be detected once the packet protection is removed. -An attacker can guess values for packet numbers and have an endpoint confirm -guesses through timing side channels. If the recipient of a packet discards +An attacker could guess values for packet numbers and have an endpoint confirm +guesses through timing side channels. Similarly, guesses for the packet number +length can be trialed and exposed. If the recipient of a packet discards packets with duplicate packet numbers without attempting to remove packet protection they could reveal through timing side-channels that the packet number matches a received packet. For authentication to be free from side-channels, -the entire process of packet number protection removal, packet number recovery, -and packet protection removal MUST be applied together without timing and other +the entire process of header protection removal, packet number recovery, and +packet protection removal MUST be applied together without timing and other side-channels. For the sending of packets, construction and protection of packet payloads and diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index 9d04abeb7c..ad565ab17a 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -2262,10 +2262,8 @@ following layout: ~~~ 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 -+-+-+-+-+-+-+-+-+ -|0|K|1|1|0|0|0|0| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| Random Bytes (160..) ... +|0|1| Random Bytes (166..) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | + + @@ -2281,8 +2279,10 @@ following layout: This design ensures that a stateless reset packet is - to the extent possible - indistinguishable from a regular packet with a short header. -The message consists of a header byte, followed by an arbitrary number of random -bytes, followed by a Stateless Reset Token. +A stateless reset uses an entire UDP datagram, starting with the first two bits +of the packet header. The remainder of the first byte and an an arbitrary +number of random bytes following it are set to unpredictable values. The last +16 bytes of the datagram contain a Stateless Reset Token. A stateless reset will be interpreted by a recipient as a packet with a short header. For the packet to appear as valid, the Random Bytes field needs to @@ -3056,6 +3056,7 @@ IP addresses has fallen below 1280 bytes, it MUST immediately cease sending QUIC packets on the affected path. This could result in termination of the connection if an alternative path cannot be found. + ### IPv4 PMTU Discovery {#v4-pmtud} Traditional ICMP-based path MTU discovery in IPv4 {{!PMTUDv4}} is potentially @@ -3085,7 +3086,6 @@ mitigate this risk. For instance, an application could: ## Special Considerations for Packetization Layer PMTU Discovery - The PADDING frame provides a useful option for PMTU probe packets. PADDING frames generate acknowledgements, but they need not be delivered reliably. As a result, the loss of PADDING frames in probe packets does not require @@ -3102,7 +3102,6 @@ increases in the size of probe packets. As QUIC probe packets need not contain application data, aggressive increases in probe size carry fewer consequences. - # Versions {#versions} QUIC versions are identified using a 32-bit unsigned number. @@ -3188,24 +3187,11 @@ value of fields. ## Packet Number Encoding and Decoding {#packet-encoding} -Packet numbers in long and short packet headers are encoded as follows. The -number of bits required to represent the packet number is first reduced by -including only a variable number of the least significant bits of the packet -number. One or two of the most significant bits of the first byte are then used -to represent how many bits of the packet number are provided, as shown in -{{pn-encodings}}. - -| First byte pattern | Encoded Length | Bits Present | -|:-------------------|:---------------|:-------------| -| 0b0xxxxxxx | 1 byte | 7 | -| 0b10xxxxxx | 2 | 14 | -| 0b11xxxxxx | 4 | 30 | -{: #pn-encodings title="Packet Number Encodings for Packet Headers"} - -Note that these encodings are similar to those in {{integer-encoding}}, but -use different values. +Packet numbers in long and short packet headers are encoded in 1 to 4 bytes. +The number of bits required to represent the packet number is reduced by +including the least significant bits of the packet number. -Finally, the encoded packet number is protected as described in Section 5.3 of +The encoded packet number is protected as described in Section 5.4 of {{QUIC-TLS}}. The sender MUST use a packet number size able to represent more than twice as @@ -3216,14 +3202,14 @@ arrives after many higher-numbered packets have been received. An endpoint SHOULD use a large enough packet number encoding to allow the packet number to be recovered even if the packet arrives after packets that are sent afterwards. -As a result, the size of the packet number encoding is at least one more than -the base 2 logarithm of the number of contiguous unacknowledged packet numbers, -including the new packet. +As a result, the size of the packet number encoding is at least one bit more +than the base-2 logarithm of the number of contiguous unacknowledged packet +numbers, including the new packet. -For example, if an endpoint has received an acknowledgment for packet 0x6afa2f, -sending a packet with a number of 0x6b2d79 requires a packet number encoding -with 14 bits or more; whereas the 30-bit packet number encoding is needed to -send a packet with a number of 0x6bc107. +For example, if an endpoint has received an acknowledgment for packet 0xabe8bc, +sending a packet with a number of 0xac5c02 requires a packet number encoding +with 16 bits or more; whereas the 24-bit packet number encoding is needed to +send a packet with a number of 0xace8fe. At a receiver, protection of the packet number is removed prior to recovering the full packet number. The full packet number is then reconstructed based on @@ -3231,12 +3217,12 @@ the number of significant bits present, the value of those bits, and the largest packet number received on a successfully authenticated packet. Recovering the full packet number is necessary to successfully remove packet protection. -Once packet number protection is removed, the packet number is decoded by -finding the packet number value that is closest to the next expected packet. -The next expected packet is the highest received packet number plus one. For -example, if the highest successfully authenticated packet had a packet number of -0xaa82f30e, then a packet containing a 14-bit value of 0x9b3 will be decoded as -0xaa8309b3. Example pseudo-code for packet number decoding can be found in +Once header protection is removed, the packet number is decoded by finding the +packet number value that is closest to the next expected packet. The next +expected packet is the highest received packet number plus one. For example, if +the highest successfully authenticated packet had a packet number of 0xa82f30ea, +then a packet containing a 16-bit value of 0x9b32 will be decoded as 0xa8309b32. +Example pseudo-code for packet number decoding can be found in {{sample-packet-number-decoding}}. @@ -3246,7 +3232,7 @@ example, if the highest successfully authenticated packet had a packet number of 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 +-+-+-+-+-+-+-+-+ -|1| Type (7) | +|1|1|T T|R R|P P| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Version (32) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -3258,7 +3244,7 @@ example, if the highest successfully authenticated packet had a packet number of +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Length (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| Packet Number (8/16/32) | +| Packet Number (8/16/24/32) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Payload (*) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -3277,15 +3263,35 @@ Header Form: : The most significant bit (0x80) of byte 0 (the first byte) is set to 1 for long headers. -Long Packet Type: +Fixed Bit: + +: The next bit (0x40) of byte 0 is set to 1. Packets containing a zero value + for this bit are not valid packets in this version and MUST be discarded. + +Long Packet Type (T): + +: The next two bits (those with a mask of 0x30) of byte 0 contain a packet type. + Packet types are listed in {{long-packet-types}}. + +Reserved Bits (R): + +: The next two bits (those with a mask of 0x0c) of byte 0 are reserved. These + bits are protected using header protection (see Section 5.4 of {{QUIC-TLS}}). + The value included prior to protection MUST be set to 0. An endpoint MUST + treat receipt of a packet that has a non-zero value for these bits after + removing protection as a connection error of type PROTOCOL_VIOLATION. -: The remaining seven bits of byte 0 contain the packet type. This field can - indicate one of 128 packet types. The types specified for this version are - listed in {{long-packet-types}}. +Packet Number Length (P): + +: The least significant two bits (those with a mask of 0x03) of byte 0 contain + the length of the packet number, encoded as an unsigned, two-bit integer that + is one less than the length of the packet number field in bytes. That is, the + length of the packet number field is the value of this field, plus one. These + bits are protected using header protection (see Section 5.4 of {{QUIC-TLS}}). Version: -: The QUIC Version is a 32-bit field that follows the Type. This field +: The QUIC Version is a 32-bit field that follows the first byte. This field indicates which version of QUIC is in use and determines how the rest of the protocol fields are interpreted. @@ -3322,9 +3328,9 @@ Length: Packet Number: -: The packet number field is 1, 2, or 4 bytes long. The packet number has +: The packet number field is 1 to 4 bytes long. The packet number has confidentiality protection separate from packet protection, as described in - Section 5.3 of {{QUIC-TLS}}. The length of the packet number field is encoded + Section 5.4 of {{QUIC-TLS}}. The length of the packet number field is encoded in the plaintext packet number. See {{packet-encoding}} for details. Payload: @@ -3333,23 +3339,18 @@ Payload: The following packet types are defined: - - | Type | Name | Section | -|:-----|:------------------------------|:----------------------------| -| 0x7F | Initial | {{packet-initial}} | -| 0x7E | Retry | {{packet-retry}} | -| 0x7D | Handshake | {{packet-handshake}} | -| 0x7C | 0-RTT Protected | {{packet-protected}} | +|-----:|:------------------------------|:----------------------------| +| 0x0 | Initial | {{packet-initial}} | +| 0x1 | 0-RTT Protected | {{packet-protected}} | +| 0x2 | Handshake | {{packet-handshake}} | +| 0x3 | Retry | {{packet-retry}} | {: #long-packet-types title="Long Header Packet Types"} -The header form, type, connection ID lengths byte, destination and source -connection IDs, and version fields of a long header packet are -version-independent. The packet number and values for packet types defined in -{{long-packet-types}} are version-specific. See {{QUIC-INVARIANTS}} for details +The header form bit, connection ID lengths byte, Destination and Source +Connection ID fields, and Version fields of a long header packet are +version-independent. The other fields in the first byte, plus the Length and +Packet Number fields are version-specific. See {{QUIC-INVARIANTS}} for details on how packets from different versions of QUIC are interpreted. The interpretation of the fields and the payload are specific to a version and @@ -3358,9 +3359,9 @@ following sections. The end of the packet is determined by the Length field. The Length field covers both the Packet Number and Payload fields, both of which are -confidentiality protected and initially of unknown length. The size of the -Payload field is learned once the packet number protection is removed. The -Length field enables packet coalescing ({{packet-coalesce}}). +confidentiality protected and initially of unknown length. The length of the +Payload field is learned once header protection is removed. The Length field +enables packet coalescing ({{packet-coalesce}}). ## Short Header Packet {#short-header} @@ -3369,11 +3370,11 @@ Length field enables packet coalescing ({{packet-coalesce}}). 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 +-+-+-+-+-+-+-+-+ -|0|K|1|1|0|S|R R| +|0|1|S|R|R|K|P P| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Destination Connection ID (0..144) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| Packet Number (8/16/32) ... +| Packet Number (8/16/24/32) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Protected Payload (*) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -3387,51 +3388,39 @@ Header Form: : The most significant bit (0x80) of byte 0 is set to 0 for the short header. -Key Phase Bit: - -: The second bit (0x40) of byte 0 indicates the key phase, which allows a - recipient of a packet to identify the packet protection keys that are used to - protect the packet. See {{QUIC-TLS}} for details. - -\[\[Editor's Note: this section should be removed and the bit definitions -changed before this draft goes to the IESG.]] +Fixed Bit: -Third Bit: +: The next bit (0x40) of byte 0 is set to 1. Packets containing a zero value + for this bit are not valid packets in this version and MUST be discarded. -: The third bit (0x20) of byte 0 is set to 1. +Spin Bit (S): -\[\[Editor's Note: this section should be removed and the bit definitions -changed before this draft goes to the IESG.]] +: The sixth bit (0x20) of byte 0 is the Latency Spin Bit, set as described in + {{!SPIN=I-D.ietf-quic-spin-exp}}. -Fourth Bit: +Reserved Bits (R): -: The fourth bit (0x10) of byte 0 is set to 1. +: The next two bits (those with a mask of 0x18) of byte 0 are reserved. These + bits are protected using header protection (see Section 5.4 of + {{QUIC-TLS}}). The value included prior to protection MUST be set to 0. An + endpoint MUST treat receipt of a packet that has a non-zero value for these + bits after removing protection as a connection error of type + PROTOCOL_VIOLATION. -\[\[Editor's Note: this section should be removed and the bit definitions -changed before this draft goes to the IESG.]] +Key Phase (K): -Google QUIC Demultiplexing Bit: - -: The fifth bit (0x8) of byte 0 is set to 0. This allows implementations of - Google QUIC to distinguish Google QUIC packets from short header packets sent - by a client because Google QUIC servers expect the connection ID to always be - present. The special interpretation of this bit SHOULD be removed from this - specification when Google QUIC has finished transitioning to the new header - format. - -Spin Bit: - -: The sixth bit (0x4) of byte 0 is the Latency Spin Bit, set as described in -{{!SPIN=I-D.ietf-quic-spin-exp}}. +: The next bit (0x04) of byte 0 indicates the key phase, which allows a + recipient of a packet to identify the packet protection keys that are used to + protect the packet. See {{QUIC-TLS}} for details. This bit is protected + using header protection (see Section 5.4 of {{QUIC-TLS}}). -Reserved: +Packet Number Length (P): -: The seventh and eighth bits (0x3) of byte 0 are reserved for - experimentation. Endpoints MUST ignore these bits on packets they receive - unless they are participating in an experiment that uses these bits. An - endpoint not actively using these bits SHOULD set the value randomly on - packets they send to protect against unwanted inference about particular - values. +: The least significant two bits (those with a mask of 0x03) of byte 0 contain + the length of the packet number, encoded as an unsigned, two-bit integer that + is one less than the length of the packet number field in bytes. That is, the + length of the packet number field is the value of this field, plus one. These + bits are protected using header protection (see Section 5.4 of {{QUIC-TLS}}). Destination Connection ID: @@ -3440,16 +3429,16 @@ Destination Connection ID: Packet Number: -: The packet number field is 1, 2, or 4 bytes long. The packet number has +: The packet number field is 1 to 4 bytes long. The packet number has confidentiality protection separate from packet protection, as described in - Section 5.3 of {{QUIC-TLS}}. The length of the packet number field is encoded - in the plaintext packet number. See {{packet-encoding}} for details. + Section 5.4 of {{QUIC-TLS}}. The length of the packet number field is encoded + in Packet Number Length field. See {{packet-encoding}} for details. Protected Payload: : Packets with a short header always include a 1-RTT protected payload. -The header form and connection ID field of a short header packet are +The header form bit and the connection ID field of a short header packet are version-independent. The remaining fields are specific to the selected QUIC version. See {{QUIC-INVARIANTS}} for details on how packets from different versions of QUIC are interpreted. @@ -3521,7 +3510,7 @@ process. ## Initial Packet {#packet-initial} -An Initial packet uses long headers with a type value of 0x7F. It carries the +An Initial packet uses long headers with a type value of 0x0. It carries the first CRYPTO frames sent by the client and server to perform key exchange, and carries ACKs in either direction. @@ -3536,7 +3525,7 @@ that are added to the Long Header before the Length field. ~~~ +-+-+-+-+-+-+-+-+ -|1| 0x7f | +|1|1| 0 |R R|P P| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Version (32) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -3552,7 +3541,7 @@ that are added to the Long Header before the Length field. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Length (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| Packet Number (8/16/32) | +| Packet Number (8/16/24/32) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Payload (*) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -3651,7 +3640,7 @@ the connection. ## Handshake Packet {#packet-handshake} -A Handshake packet uses long headers with a type value of 0x7D. It is +A Handshake packet uses long headers with a type value of 0x3. It is used to carry acknowledgments and cryptographic handshake messages from the server and client. @@ -3683,7 +3672,7 @@ wishes to perform a stateless retry (see {{validate-handshake}}). 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 +-+-+-+-+-+-+-+-+ -|1| 0x7e | +|1|1| 3 |ODCIL(4| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Version (32) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -3693,7 +3682,7 @@ wishes to perform a stateless retry (see {{validate-handshake}}). +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Connection ID (0/32..144) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| ODCIL(8) | Original Destination Connection ID (*) | +| Original Destination Connection ID (0/32..144) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Retry Token (*) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -3709,11 +3698,11 @@ Packet Number, and Payload fields. These are replaced with: ODCIL: -: The length of the Original Destination Connection ID field. The length is - encoded in the least significant 4 bits of the byte, using the same encoding - as the DCIL and SCIL fields. The most significant 4 bits of this byte are - reserved. Unless a use for these bits has been negotiated, endpoints SHOULD - send randomized values and MUST ignore any value that it receives. +: The four least-significant bits of the first byte of a Retry packet are not + protected as they are for other packets with the long header, because Retry + packets don't contain a protected payload. These bits instead encode the + length of the Original Destination Connection ID field. The length uses the + same encoding as the DCIL and SCIL fields. Original Destination Connection ID: @@ -5320,7 +5309,7 @@ from 0xFF00 to 0xFFFF are reserved for Private Use {{!RFC8126}}. # Sample Packet Number Decoding Algorithm {#sample-packet-number-decoding} The following pseudo-code shows how an implementation can decode packet -numbers after packet number protection has been removed. +numbers after header protection has been removed. ~~~ DecodePacketNumber(largest_pn, truncated_pn, pn_nbits):