From 23018df88dccf39f1af4ebdfa3c8bbed02354769 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Mon, 29 Jan 2018 16:51:58 +1100 Subject: [PATCH 01/18] Initial cut at packet number encryption This is a little rough, but I think that the bones are here. I know that we discussed removing short packet types in favor of putting the lengths under encryption. I will do that separately, just to keep the size of this changeset to something more manageable. --- draft-ietf-quic-tls.md | 157 +++++++++++++++++++++++++++++------ draft-ietf-quic-transport.md | 155 ++++++++++++---------------------- 2 files changed, 187 insertions(+), 125 deletions(-) diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index bd269ab365..41bf664dbc 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -44,14 +44,6 @@ normative: org: Mozilla role: editor - FIPS180: - title: NIST FIPS 180-4, Secure Hash Standard - author: - name: NIST - ins: National Institute of Standards and Technology, U.S. Department of Commerce - date: 2012-03 - target: http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf - informative: AEBounds: @@ -729,8 +721,8 @@ server_handshake_secret = ~~~ The hash function for HKDF when deriving handshake secrets and keys is SHA-256 -{{FIPS180}}. The connection ID used with QHKDF-Expand is the connection ID -chosen by the client. +{{!SHA=DOI.10.6028/NIST.FIPS.180-4}}. The connection ID used with QHKDF-Expand +is the connection ID chosen by the client. The handshake salt is a 20 octet sequence shown in the figure in hexadecimal notation. Future versions of QUIC SHOULD generate a new salt value, thus @@ -825,12 +817,16 @@ in Section 5.3 of {{!TLS13}}, the IV length is the larger of 8 or N_MIN (see Section 4 of {{!AEAD=RFC5116}}; all ciphersuites defined in {{!TLS13}} have N_MIN set to 12). -For any secret S, the AEAD key uses a label of "key", and the IV uses a label of -"iv": +The size of the packet protection key is determined by the packet protection +algorithm, see {{pn-encrypt}}. + +For any secret S, the AEAD key uses a label of "key", the IV uses a label of +"iv", packet number encryption uses a label of "pn": ~~~ key = QHKDF-Expand(S, "key", key_length) -iv = QHKDF-Expand(S, "iv", iv_length) +iv = QHKDF-Expand(S, "iv", iv_length) +pn_key = QHKDF-Expand(S, "pn", pn_key_length) ~~~ Separate keys are derived for packet protection by clients and servers. Each @@ -842,9 +838,10 @@ derived from 1-RTT secrets as follows: ~~~ client_pp_key = QHKDF-Expand(client_pp_secret, "key", 16) client_pp_iv = QHKDF-Expand(client_pp_secret, "iv", 12) +client_pp_pn = QHKDF-Expand(client_pp_secret, "pn", 12) ~~~ -The QUIC record protection initially starts with keying material derived from +The QUIC packet protection initially starts with keying material derived from handshake keys. For a client, when the TLS state machine reports that the ClientHello has been sent, 0-RTT keys can be generated and installed for writing, if 0-RTT is available. Finally, the TLS state machine reports @@ -859,6 +856,11 @@ used for QUIC packet protection is 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 encryption +({{pn-encrypt}}). Thus, the unprotected packet number is part of the AAD. When +removing packet protection, an endpoint first removes the protection from the +packet number. + All QUIC packets other than Version Negotiation and Stateless Reset packets are protected with an AEAD algorithm {{!AEAD}}. Prior to establishing a shared secret, packets are protected with AEAD_AES_128_GCM and a key derived from the @@ -919,6 +921,85 @@ the connection that is hosted on stream 0. This sequence number is not visible to QUIC. +## Packet Number Protection {#pn-encrypt} + +QUIC packets are protected using a key that is derived from the current set of +secrets. The key derived using the "pn" label is used to protect the packet +number from casual observation. The packet number protection algorithm depends +on the negotiated AEAD. + +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. For packets with a long header, the ciphertext starting +immediately after the packet number is used (that is, octet 17 onwards). For +packets with a short header, the packet number length is not known, so it is +assumed to be its largest possible length (4 octets). Thus, for a short header, +the sampled ciphertext starts at either octet 5 when the connection ID is +omitted, or octet 13 when the connection is present. + +The protected packet might not have produced enough input for the negotiated +packet protection algorithm. This might happen if a packet with a short header +contains minimal data and uses a packet number encoding that is shorter than 4 +octets. Additional zero octets are added to the end of the sequence to reach +the required amount of data. + +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 {{!RFC5116}}), and +AEAD_CHACHA20_POLY1305 ({{!CHACHA=RFC7539}}). + + +### AES-Based Packet Number Protection + +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 ECB mode. +AEAD_AES_256_GCM, and AEAD_AES_256_CCM use 256-bit AES in ECB mode. + +This algorithm samples 16 octets from the packet ciphertext. This input is used +as the AES initialization vector (IV). This value is input to AES that is keyed +using the current packet protection key. + +The output of AES is truncated to the length of the encoded packet number. The +protected packet number is the exclusive-OR (XOR) of the encoded packet number +and the truncated output. + +In summary, packet protection with AES uses the following pseudocode: + +~~~ +encoded = EncodePacketNumber(packet_number) +len = Length(encoded) +sample = ZeroPadSlice(ciphertext, offset, 16) +encrypted_pn = encoded XOR AES(pn_key, sample)[0..len] +~~~ + + +### ChaCha20-Based Packet Number Protection + +When AEAD_CHACHA20_POLY1305 is in use, packet number protection uses the +ChaCha20 block function as defined in Section 2.3 of {{!CHACHA}}. This uses a +256-bit key and 16 octets sampled from the packet protection output. + +The first 4 octets 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 octets +are interpreted as three concatenated 32-bit numbers in little-endian order and +used as the nonce. + +The output of the ChaCha20 block function is truncated to the length of the +encoded packet number. The protected packet number is the exclusive-OR (XOR) of +the encoded packet number and the truncated output. + +In summary, packet protection with ChaCha20 uses the following pseudocode: + +~~~ +encoded = EncodePacketNumber(packet_number) +len = Length(encoded) +sample = ZeroPadSlice(ciphertext, offset, 16) +encrypted_pn = encoded XOR ChaCha20(pn_key, sample)[0..len] +~~~ + + ## Receiving Protected Packets Once an endpoint successfully receives a packet with a given packet number, it @@ -934,17 +1015,6 @@ used in QUIC can cause packet numbers to be decoded incorrectly if they are delayed significantly. -## Packet Number Gaps {#packet-number-gaps} - -Section 6.8.5.1 of {{QUIC-TRANSPORT}} also requires a secret to compute packet -number gaps on connection ID transitions. That secret is computed as: - -~~~ -packet_number_secret = - TLS-Exporter("EXPORTER-QUIC packet number", "", Hash.length) -~~~ - - # Key Phases As TLS reports the availability of 0-RTT and 1-RTT keys, new keying material can @@ -1551,6 +1621,43 @@ 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} + +Packet number protection relies on the randomness of the AEAD output, which is a +property that AEAD algorithms do not guarantee. Therefore, no strong assurances +about the general security of this mechanism can be proven. + +Use of the same key and nonce for encryption for encryption can weaken +encryption. For the schemes described, protecting two packet numbers with the +same key and nonce would reveal the packet number. For packet number protection +to be effective, the output of the packet protection AEAD needs to be +effectively random. + +All the AEAD functions used meet indistinguishability under (adaptive) chosen +plaintext attack (IND-CPA, IND-CPA2) goals and produce minimal expansion of the +plaintext, adding only an authentication tag. Therefore, this document assumes +that the sampled AEAD output is unpredictable and not subject to influence by an +attacker. Based on this assumption, the odds of producing identical input to a +packet protection algorithm approach the birthday bound on the size of the input +(that is, one divided by the square root of the number of possible values). + +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 the packet number protection. A falsified +or modified packet number can only be detected once the packet protection is +removed. + +For authentication to be effective, packet number protection MUST be applied and +removed without timing or other side-channels. For a recipient of a packet, the +process for recovering the full packet number also needs to free from +side-channels. This includes recovery of variable-length packet numbers. + + + # Error Codes {#errors} This section defines error codes from the error code space used in diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index d8304f18a1..c815674dd6 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -345,7 +345,8 @@ Payload Length: Packet Number: : The Packet Number is a 32-bit field that follows the two connection IDs. - {{packet-numbers}} describes the use of packet numbers. + {{packet-numbers}} describes the use of packet numbers. Packet numbers are + protected separate to the packet payload. Payload: @@ -452,7 +453,8 @@ Destination Connection ID: Packet Number: : The length of the packet number field depends on the packet type. This field - can be 1, 2 or 4 octets long depending on the short packet type. + can be 1, 2 or 4 octets long depending on the short packet type. Packet + numbers are protected separate to the packet payload. Protected Payload: @@ -577,9 +579,9 @@ results in a change to the keys used to protect the Initial packet. The client populates the Source Connection ID field with a value of its choosing and sets the low bits of the ConnID Len field to match. -The first Initial packet that is sent by a client contains a randomized packet -number. All subsequent packets contain a packet number that is incremented by -one, see ({{packet-numbers}}). +The first Initial packet that is sent by a client contains a packet number of 0. +All subsequent packets contain a packet number that is incremented by one, see +({{packet-numbers}}). The payload of an Initial packet conveys a STREAM frame (or frames) for stream 0 containing a cryptographic handshake message. The stream in this packet @@ -612,8 +614,11 @@ The server includes a connection ID of its choice in the Source Connection ID field. The client MUST use this connection ID in the Destination Connection ID of subsequent packets that it sends. -The packet number field echoes the packet number field from the triggering -client packet. +The Packet Number field of a Retry packet MUST be set to 0. This value is +subsequently protected as normal. \[\[Editor's Note: This isn't ideal, because +it creates a "cheat" where the client assumes a value. That's a problem, so I'm +tempted to suggest that this include any value less than 2^30 so that normal +processing works - and can be properly exercised.]] A Retry packet is never explicitly acknowledged in an ACK frame by a client. Receiving another Initial packet implicitly acknowledges a Retry @@ -650,11 +655,8 @@ ID that is chosen by the recipient of the packet; the Source Connection ID includes the connection ID that the sender of the packet wishes to use (see {{connection-id}}). -The first Handshake packet sent by a server contains a randomized packet number. -This value is increased for each subsequent packet sent by the server as -described in {{packet-numbers}}. The client increments the packet number from -its previous packet by one for each Handshake packet that it sends (which might -be an Initial, 0-RTT Protected, or Handshake packet). +The first Handshake packet sent by a server contains a packet number of 0. +Packet numbers are incremented normally for other Handshake packets. Servers MUST NOT send more than three Handshake packets without receiving a packet from a verified source address. Source addresses can be verified @@ -676,10 +678,11 @@ CONNECTION_CLOSE frames if the handshake is unsuccessful. ## Protected Packets {#packet-protected} -Packets that are protected with 0-RTT keys are sent with long headers; all -packets protected with 1-RTT keys are sent with short headers. The different -packet types explicitly indicate the encryption level and therefore the keys -that are used to remove packet protection. +All QUIC packets are protected. Packets that are protected with the static +handshake keys or the 0-RTT keys are sent with long headers; all packets +protected with 1-RTT keys are sent with short headers. The different packet +types explicitly indicate the encryption level and therefore the keys that are +used to remove packet protection. Packets protected with 0-RTT keys use a type value of 0x7C. The connection ID fields for a 0-RTT packet MUST match the values used in the Initial packet @@ -693,8 +696,10 @@ continue to use the same Destination Connection ID for 0-RTT packets, see The version field for protected packets is the current QUIC version. -The packet number field contains a packet number, which increases with each -packet sent, see {{packet-numbers}} for details. +The packet number field contains a packet number, which is protected separately +from the rest of the packet (see {{QUIC-TLS}} for details). The underlying +packet number increases with each packet sent, see {{packet-numbers}} for +details. The payload is protected using authenticated encryption. {{QUIC-TLS}} describes packet protection in detail. After decryption, the plaintext consists of a @@ -770,8 +775,8 @@ response to connection migration ({{migration}}). NEW_CONNECTION_ID frames The packet number is an integer in the range 0 to 2^62-1. The value is used in determining the cryptographic nonce for packet encryption. Each endpoint maintains a separate packet number for sending and receiving. The packet number -for sending MUST increase by at least one after sending any packet, unless -otherwise specified (see {{initial-packet-number}}). +for sending MUST starts at zero for the first packet set and MUST increase by at +least one after sending a packet. A QUIC endpoint MUST NOT reuse a packet number within the same connection (that is, under the same cryptographic keys). If the packet number for sending @@ -781,15 +786,17 @@ Reset ({{stateless-reset}}) in response to further packets that it receives. For the packet header, the number of bits required to represent the packet number are reduced by including only the least significant bits of the packet -number. The actual packet number for each packet is reconstructed at the -receiver based on the largest packet number received on a successfully -authenticated packet. - -A 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 16-bit -value of 0x1f94 will be decoded as 0xaa831f94. +number. The encoded packet number is protected as described in {{QUIC-TLS}}. +Protection of the packet number is removed prior to recovering the full packet +number. The full packet number is reconstructed at the receiver based on the +largest packet number received on a successfully authenticated packet. + +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 16-bit value of 0x1f94 will be decoded as +0xaa831f94. The sender MUST use a packet number size able to represent more than twice as large a range than the difference between the largest acknowledged packet and @@ -813,26 +820,6 @@ number. The Retry packet ({{packet-retry}}) has special rules for populating the packet number field. -### Initial Packet Number {#initial-packet-number} - -The initial value for packet number MUST be selected randomly from a range -between 0 and 2^32 - 1025 (inclusive). This value is selected so that Initial -and Handshake packets exercise as many possible values for the Packet Number -field as possible. - -Limiting the range allows both for loss of packets and for any stateless -exchanges. Packet numbers are incremented for subsequent packets, but packet -loss and stateless handling can both mean that the first packet sent by an -endpoint isn't necessarily the first packet received by its peer. The first -packet received by a peer cannot be 2^32 or greater or the recipient will -incorrectly assume a packet number that is 2^32 values lower and discard the -packet. - -Use of a secure random number generator {{?RFC4086}} is not necessary for -generating the initial packet number, nor is it necessary that the value be -uniformly distributed. - - # Frames and Frame Types {#frames} The payload of all packets, after removing packet protection, consists of a @@ -1776,35 +1763,26 @@ restart the alarm for a longer period of time. ### Privacy Implications of Connection Migration {#migration-linkability} Using a stable connection ID on multiple network paths allows a passive observer -to correlate activity between those paths. An endpoint that moves between -networks might not wish to have their activity correlated by any entity other -than a server. The NEW_CONNECTION_ID message can be sent by both endpoints to -provide an unlinkable connection ID for use in case a peer wishes to explicitly -break linkability between two points of network attachment. - -An endpoint might need to send packets on multiple networks without receiving -any response from its peer. To ensure that the endpoint is not linkable -across each of these changes, a new connection ID and packet number gap are -needed for each network. To support this, each endpoint sends multiple -NEW_CONNECTION_ID messages. Each NEW_CONNECTION_ID is marked with a sequence -number. Connection IDs MUST be used in the order in which they are numbered. +to correlate activity between those paths. A client that moves between networks +might not wish to have their activity correlated by any entity other than a +server. The NEW_CONNECTION_ID message can be sent by a server to provide an +unlinkable connection ID for use in case the client wishes to explicitly break +linkability between two points of network attachment. An endpoint that does not require the use of a connection ID should not request that its peer use a connection ID. Such an endpoint does not need to provide new connection IDs using the NEW_CONNECTION_ID frame. -An endpoint which wishes to break linkability upon changing networks MUST use -the connection ID provided by its peer as well as incrementing the packet -sequence number by an externally unpredictable value computed as described in -{{packet-number-gap}}. Packet number gaps are cumulative. An endpoint might -skip connection IDs, but it MUST ensure that it applies the associated packet -number gaps for connection IDs that it skips in addition to the packet number -gap associated with the connection ID that it does use. +A client might need to send packets on multiple networks without receiving any +response from the server. To ensure that the client is not linkable across each +of these changes, a new connection ID is needed for each network. To support +this, a server sends multiple NEW_CONNECTION_ID messages. Each +NEW_CONNECTION_ID is marked with a sequence number. Connection IDs MUST be used +in the order in which they are numbered. -An endpoint that receives a packet that is marked with a new connection ID -recovers the packet number by adding the cumulative packet number gap to its -expected packet number. An endpoint MUST discard packets that contain a smaller -gap than it advertised. +A client which wishes to break linkability upon changing networks MUST use the +connection ID provided by the server. Protection of packet numbers ensures that +packet numbers cannot be used to correlate connections. Clients MAY change connection ID at any time based on implementation-specific concerns. For example, after a period of network inactivity NAT rebinding might @@ -1828,29 +1806,6 @@ allow for use of that connection ID to link activity on new paths. There is no need to move to a new connection ID if the address of a peer changes without also changing the connection ID. -For instance, a server might provide a packet number gap of 7 associated with a -new connection ID. If the server received packet 10 using the previous -connection ID, it should expect packets on the new connection ID to start at 18. -A packet with the new connection ID and a packet number of 17 is discarded as -being in error. - - -#### Packet Number Gap - -In order to avoid linkage, the packet number gap MUST be externally -indistinguishable from random. The packet number gap for a connection -ID with sequence number is computed by encoding the sequence number -as a 32-bit integer in big-endian format, and then computing: - -~~~ -Gap = HKDF-Expand-Label(packet_number_secret, - "QUIC packet sequence gap", sequence, 4) -~~~ - -The output of HKDF-Expand-Label is interpreted as a big-endian -number. "packet_number_secret" is derived from the TLS key exchange, -as described in Section 5.6 of {{QUIC-TLS}}. - ## Connection Termination {#termination} @@ -2583,11 +2538,11 @@ Unlike TCP SACKs, QUIC acknowledgements are irrevocable. Once a packet has been acknowledged, even if it does not appear in a future ACK frame, it remains acknowledged. -A client MUST NOT acknowledge Retry packets. Retry packets include the packet -number from the Initial packet it responds to. Version Negotiation packets -cannot be acknowledged because they do not contain a packet number. Rather than -relying on ACK frames, these packets are implicitly acknowledged by the next -Initial packet sent by the client. +A client MUST NOT acknowledge Retry packets. Version +Negotiation packets don't contain a packet number and Retry packets include the +packet number from the Initial packet it responds to. Rather than relying on +ACK frames, these packets are implicitly acknowledged by the next Initial packet +sent by the client. An ACK frame is shown below. From 41196efd08bd194cba92678ec06cc8bc06914965 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Mon, 29 Jan 2018 17:10:45 +1100 Subject: [PATCH 02/18] Constant time This is pretty onerous, so I'd like to see if people think that this is acceptable. The cost is that all packets need to have their AEAD run the whole way through. The gain is that there will be no side-channels for attackers to exploit. --- draft-ietf-quic-tls.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index 41bf664dbc..747a425b75 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -1651,11 +1651,17 @@ are transitively authenticated using the packet number protection. A falsified or modified packet number can only be detected once the packet protection is removed. -For authentication to be effective, packet number protection MUST be applied and -removed without timing or other side-channels. For a recipient of a packet, the -process for recovering the full packet number also needs to free from -side-channels. This includes recovery of variable-length packet numbers. - +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 +duplicate packets without attempting to remove packet protection they will +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 side-channels. + +For the sending of packets, construction and protection of packet payloads and +packet numbers MUST be free from side-channels that would reveal the packet +number or its encoded size. # Error Codes {#errors} From 1d6b9793138a03b0ec93bd86199c375a5179403b Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Mon, 29 Jan 2018 18:26:03 +1100 Subject: [PATCH 03/18] That was a little unclear on a re-read --- draft-ietf-quic-tls.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index 747a425b75..d8d09e86d9 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -1636,10 +1636,11 @@ effectively random. All the AEAD functions used meet indistinguishability under (adaptive) chosen plaintext attack (IND-CPA, IND-CPA2) goals and produce minimal expansion of the plaintext, adding only an authentication tag. Therefore, this document assumes -that the sampled AEAD output is unpredictable and not subject to influence by an -attacker. Based on this assumption, the odds of producing identical input to a -packet protection algorithm approach the birthday bound on the size of the input -(that is, one divided by the square root of the number of possible values). +that each bit of sampled AEAD output contains one bit of entropy and that an +attacker is unable to reduce this without knowledge of the key. Based on this +assumption, the odds of producing identical input to a packet protection +algorithm approach the birthday bound on the size of the input (that is, one +divided by the square root of the number of possible values). Note: From 16b663ae1bdef3bcd8ac90c967b3cac7ebded4f8 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Mon, 29 Jan 2018 18:27:53 +1100 Subject: [PATCH 04/18] That was a little unclear on a re-read, again --- draft-ietf-quic-tls.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index d8d09e86d9..d72292f15f 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -1638,9 +1638,9 @@ plaintext attack (IND-CPA, IND-CPA2) goals and produce minimal expansion of the plaintext, adding only an authentication tag. Therefore, this document assumes that each bit of sampled AEAD output contains one bit of entropy and that an attacker is unable to reduce this without knowledge of the key. Based on this -assumption, the odds of producing identical input to a packet protection -algorithm approach the birthday bound on the size of the input (that is, one -divided by the square root of the number of possible values). +assumption, the odds of two samples of ciphertext approach the birthday bound +for the size of the sample (that is, two to the negative power of half the +number of sampled bits). Note: From 1ea1ae5bf6d2784399805ee9a397bbbecc9eb645 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Mon, 29 Jan 2018 18:29:08 +1100 Subject: [PATCH 05/18] More tweaking (I have to stop this) --- draft-ietf-quic-tls.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index d72292f15f..798f51dc26 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -1654,11 +1654,12 @@ 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 -duplicate packets without attempting to remove packet protection they will -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 side-channels. +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 +side-channels. For the sending of packets, construction and protection of packet payloads and packet numbers MUST be free from side-channels that would reveal the packet From 232572553a97191ddf55f025486b0051c5598491 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Tue, 30 Jan 2018 09:52:39 +1100 Subject: [PATCH 06/18] Some fairly obvious errors --- draft-ietf-quic-tls.md | 12 ++++++------ draft-ietf-quic-transport.md | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index 798f51dc26..9dbd2820d8 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -1638,9 +1638,9 @@ plaintext attack (IND-CPA, IND-CPA2) goals and produce minimal expansion of the plaintext, adding only an authentication tag. Therefore, this document assumes that each bit of sampled AEAD output contains one bit of entropy and that an attacker is unable to reduce this without knowledge of the key. Based on this -assumption, the odds of two samples of ciphertext approach the birthday bound -for the size of the sample (that is, two to the negative power of half the -number of sampled bits). +assumption, the odds of two samples of ciphertext being identical approach the +birthday bound for the size of the sample (that is, two to the negative power of +half the number of sampled bits). Note: @@ -1648,9 +1648,9 @@ Note: protection algorithm might be used. To prevent an attacker from modifying packet numbers, values of packet numbers -are transitively authenticated using the packet number protection. A falsified -or modified packet number can only be detected once the packet protection is -removed. +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. 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 diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index c815674dd6..2050f8f756 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -580,8 +580,8 @@ The client populates the Source Connection ID field with a value of its choosing and sets the low bits of the ConnID Len field to match. The first Initial packet that is sent by a client contains a packet number of 0. -All subsequent packets contain a packet number that is incremented by one, see -({{packet-numbers}}). +All subsequent packets contain a packet number that is incremented by at least +one, see ({{packet-numbers}}). The payload of an Initial packet conveys a STREAM frame (or frames) for stream 0 containing a cryptographic handshake message. The stream in this packet @@ -775,7 +775,7 @@ response to connection migration ({{migration}}). NEW_CONNECTION_ID frames The packet number is an integer in the range 0 to 2^62-1. The value is used in determining the cryptographic nonce for packet encryption. Each endpoint maintains a separate packet number for sending and receiving. The packet number -for sending MUST starts at zero for the first packet set and MUST increase by at +for sending MUST start at zero for the first packet sent and MUST increase by at least one after sending a packet. A QUIC endpoint MUST NOT reuse a packet number within the same connection (that From 86f262d5ea72c250d2806b8145e8b2d6a4d3f207 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Tue, 30 Jan 2018 12:45:19 +1100 Subject: [PATCH 07/18] Don't mess with ChaCha20, use it directly --- draft-ietf-quic-tls.md | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index 9dbd2820d8..c93f3fe647 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -978,7 +978,7 @@ encrypted_pn = encoded XOR AES(pn_key, sample)[0..len] ### ChaCha20-Based Packet Number Protection When AEAD_CHACHA20_POLY1305 is in use, packet number protection uses the -ChaCha20 block function as defined in Section 2.3 of {{!CHACHA}}. This uses a +raw ChaCha20 function as defined in Section 2.4 of {{!CHACHA}}. This uses a 256-bit key and 16 octets sampled from the packet protection output. The first 4 octets of the sampled ciphertext are interpreted as a 32-bit number @@ -986,17 +986,13 @@ in little-endian order and are used as the block count. The remaining 12 octets are interpreted as three concatenated 32-bit numbers in little-endian order and used as the nonce. -The output of the ChaCha20 block function is truncated to the length of the -encoded packet number. The protected packet number is the exclusive-OR (XOR) of -the encoded packet number and the truncated output. - -In summary, packet protection with ChaCha20 uses the following pseudocode: +The encoded packet number is encrypted with ChaCha20 directly. In pseudocode: ~~~ encoded = EncodePacketNumber(packet_number) -len = Length(encoded) -sample = ZeroPadSlice(ciphertext, offset, 16) -encrypted_pn = encoded XOR ChaCha20(pn_key, sample)[0..len] +counter = DecodeLE(sample[0..3]) +nonce = DecodeLE(sample[4..7], sample[8..11], sample[12..15]) +encrypted_pn = ChaCha20(pn_key, counter, nonce, encoded) ~~~ From 1aec4b0936d3e30964eaeb05a17218fee76585c7 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Tue, 30 Jan 2018 14:21:10 +1100 Subject: [PATCH 08/18] Fix off-by-one error --- draft-ietf-quic-tls.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index c93f3fe647..97d26e4d8f 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -971,7 +971,7 @@ In summary, packet protection with AES uses the following pseudocode: encoded = EncodePacketNumber(packet_number) len = Length(encoded) sample = ZeroPadSlice(ciphertext, offset, 16) -encrypted_pn = encoded XOR AES(pn_key, sample)[0..len] +encrypted_pn = encoded XOR AES(pn_key, sample)[0..len-1] ~~~ From a5a6df0d111aba0dbd395e21c3b6421c425c57c7 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Wed, 31 Jan 2018 15:20:35 +1100 Subject: [PATCH 09/18] Two *different* packet numbers --- draft-ietf-quic-tls.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index 97d26e4d8f..26543b6dc6 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -1624,8 +1624,9 @@ property that AEAD algorithms do not guarantee. Therefore, no strong assurances about the general security of this mechanism can be proven. Use of the same key and nonce for encryption for encryption can weaken -encryption. For the schemes described, protecting two packet numbers with the -same key and nonce would reveal the packet number. For packet number protection +encryption. For the schemes described, protecting two different packet numbers +with the same key and nonce reveals the exclusive OR of those packet numbers, +which might be used to compromise confidentiality. For packet number protection to be effective, the output of the packet protection AEAD needs to be effectively random. From e641b72665393e49fa3d1d9a7292914c74fda09b Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Thu, 1 Feb 2018 12:01:01 +1100 Subject: [PATCH 10/18] Remove repetition --- draft-ietf-quic-tls.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index 26543b6dc6..5b6ab21cff 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -1623,11 +1623,11 @@ Packet number protection relies on the randomness of the AEAD output, which is a property that AEAD algorithms do not guarantee. Therefore, no strong assurances about the general security of this mechanism can be proven. -Use of the same key and nonce for encryption for encryption can weaken -encryption. For the schemes described, protecting two different packet numbers -with the same key and nonce reveals the exclusive OR of those packet numbers, -which might be used to compromise confidentiality. For packet number protection -to be effective, the output of the packet protection AEAD needs to be +Use of the same key and nonce more than once can weaken the guarantees provided +by this protection. For the schemes described, protecting two different packet +numbers with the same key and nonce reveals the exclusive OR of those packet +numbers, which might be used to compromise confidentiality. For packet number +protection to be effective, the output of the packet protection AEAD needs to be effectively random. All the AEAD functions used meet indistinguishability under (adaptive) chosen From 379102013dda2655eb7b68304c7892794dc51996 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Fri, 2 Feb 2018 14:18:34 +1100 Subject: [PATCH 11/18] Take and rework suggestions by @cwood --- draft-ietf-quic-tls.md | 106 ++++++++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 44 deletions(-) diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index 5b6ab21cff..a3d6a45ef8 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -54,6 +54,15 @@ informative: date: 2016-03-08 target: "http://www.isg.rhul.ac.uk/~kp/TLS-AEbounds.pdf" + IMC: + title: "Introduction to Modern Cryptography, Second Edition" + author: + - ins: J. Katz + - ins: Y. Lindell + date: 2014-11-06 + seriesinfo: + ISBN: 978-1466570269 + QUIC-HTTP: title: "Hypertext Transfer Protocol (HTTP) over QUIC" date: {DATE} @@ -930,18 +939,26 @@ on the negotiated AEAD. 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. For packets with a long header, the ciphertext starting -immediately after the packet number is used (that is, octet 17 onwards). For -packets with a short header, the packet number length is not known, so it is -assumed to be its largest possible length (4 octets). Thus, for a short header, -the sampled ciphertext starts at either octet 5 when the connection ID is -omitted, or octet 13 when the connection is present. - -The protected packet might not have produced enough input for the negotiated -packet protection algorithm. This might happen if a packet with a short header -contains minimal data and uses a packet number encoding that is shorter than 4 -octets. Additional zero octets are added to the end of the sequence to reach -the required amount of data. +encryption algorithm. + +For packets with a long header, the ciphertext starting +immediately after the packet number is used (that is, octet 17 onwards). + +For packets with a short header, the packet number length is not known before +decryption, so it is assumed to be the smaller of the maximum possible packet +number encoding (4 octets), or the size of the protected packet minus the +minimum expansion for the AEAD. Thus, the sampled ciphertext for a short header +can be determined by: + +``` +sample_offset = min(1 + connection_id_length + 4, + packet_length - aead_expansion) +sample = packet[sample_offset..sample_offset+sample_length] +``` + +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. 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 @@ -954,24 +971,21 @@ AEAD_CHACHA20_POLY1305 ({{!CHACHA=RFC7539}}). 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 ECB mode. -AEAD_AES_256_GCM, and AEAD_AES_256_CCM use 256-bit AES in ECB 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 octets from the packet ciphertext. This input is used -as the AES initialization vector (IV). This value is input to AES that is keyed -using the current packet protection key. +This algorithm samples 16 octets from the packet ciphertext. This value is +input to AES that is keyed using the packet protection key. The output of AES is truncated to the length of the encoded packet number. The protected packet number is the exclusive-OR (XOR) of the encoded packet number and the truncated output. -In summary, packet protection with AES uses the following pseudocode: +In summary, packet protection with AES uses the following form: ~~~ -encoded = EncodePacketNumber(packet_number) -len = Length(encoded) -sample = ZeroPadSlice(ciphertext, offset, 16) -encrypted_pn = encoded XOR AES(pn_key, sample)[0..len-1] +encrypted_pn = packet_number XOR AES(pn_key, sample) ~~~ @@ -986,13 +1000,13 @@ in little-endian order and are used as the block count. The remaining 12 octets are interpreted as three concatenated 32-bit numbers in little-endian order and used as the nonce. -The encoded packet number is encrypted with ChaCha20 directly. In pseudocode: +The encoded packet number is then encrypted with ChaCha20 directly. In +pseudocode: ~~~ -encoded = EncodePacketNumber(packet_number) counter = DecodeLE(sample[0..3]) nonce = DecodeLE(sample[4..7], sample[8..11], sample[12..15]) -encrypted_pn = ChaCha20(pn_key, counter, nonce, encoded) +encrypted_pn = ChaCha20(pn_key, counter, nonce, packet_number) ~~~ @@ -1619,25 +1633,29 @@ packets as indicative of an attack. ## Packet Number Protection Analysis {#pn-encrypt-analysis} -Packet number protection relies on the randomness of the AEAD output, which is a -property that AEAD algorithms do not guarantee. Therefore, no strong assurances -about the general security of this mechanism can be proven. - -Use of the same key and nonce more than once can weaken the guarantees provided -by this protection. For the schemes described, protecting two different packet -numbers with the same key and nonce reveals the exclusive OR of those packet -numbers, which might be used to compromise confidentiality. For packet number -protection to be effective, the output of the packet protection AEAD needs to be -effectively random. - -All the AEAD functions used meet indistinguishability under (adaptive) chosen -plaintext attack (IND-CPA, IND-CPA2) goals and produce minimal expansion of the -plaintext, adding only an authentication tag. Therefore, this document assumes -that each bit of sampled AEAD output contains one bit of entropy and that an -attacker is unable to reduce this without knowledge of the key. Based on this -assumption, the odds of two samples of ciphertext being identical approach the -birthday bound for the size of the sample (that is, two to the negative power of -half the number of sampled bits). +Packet number protection relies 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: + +``` +encrypted_pn = packet_number 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. Note: From 0f3c970169c9a2c20e7b61509f979f731d303f7c Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Fri, 2 Feb 2018 15:19:48 +1100 Subject: [PATCH 12/18] Just use AES-CTR --- draft-ietf-quic-tls.md | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index a3d6a45ef8..c9753ef75f 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -972,20 +972,14 @@ AEAD_CHACHA20_POLY1305 ({{!CHACHA=RFC7539}}). 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 -Electronic Code-Book (ECB) mode. AEAD_AES_256_GCM, and AEAD_AES_256_CCM use -256-bit AES in ECB mode. +counter (CTR) mode. AEAD_AES_256_GCM, and AEAD_AES_256_CCM use +256-bit AES in CTR mode. This algorithm samples 16 octets from the packet ciphertext. This value is -input to AES that is keyed using the packet protection key. - -The output of AES is truncated to the length of the encoded packet number. The -protected packet number is the exclusive-OR (XOR) of the encoded packet number -and the truncated output. - -In summary, packet protection with AES uses the following form: +used as the counter input to AES-CTR. ~~~ -encrypted_pn = packet_number XOR AES(pn_key, sample) +encrypted_pn = AES-CTR(pn_key, sample, packet_number) ~~~ From 0c54fbf0e1cbcb5d094d86fe649273f7ae5d8d45 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Wed, 7 Feb 2018 11:29:50 +1100 Subject: [PATCH 13/18] Make the order of operations clearer. --- draft-ietf-quic-transport.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index 2050f8f756..192c769163 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -786,10 +786,13 @@ Reset ({{stateless-reset}}) in response to further packets that it receives. For the packet header, the number of bits required to represent the packet number are reduced by including only the least significant bits of the packet -number. The encoded packet number is protected as described in {{QUIC-TLS}}. -Protection of the packet number is removed prior to recovering the full packet -number. The full packet number is reconstructed at the receiver based on the -largest packet number received on a successfully authenticated packet. +number. + +The encoded packet number is protected as described in {{QUIC-TLS}}. Protection +of the packet number is removed prior to recovering the full packet number. The +full packet number is reconstructed at the receiver based on 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. From f163e2ab2fbd7064a01e76a06b999f80a11b5c9b Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Wed, 4 Apr 2018 16:09:12 +1000 Subject: [PATCH 14/18] Revert unnecessary change --- draft-ietf-quic-transport.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index 192c769163..a7bf765b70 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -2541,11 +2541,11 @@ Unlike TCP SACKs, QUIC acknowledgements are irrevocable. Once a packet has been acknowledged, even if it does not appear in a future ACK frame, it remains acknowledged. -A client MUST NOT acknowledge Retry packets. Version -Negotiation packets don't contain a packet number and Retry packets include the -packet number from the Initial packet it responds to. Rather than relying on -ACK frames, these packets are implicitly acknowledged by the next Initial packet -sent by the client. +A client MUST NOT acknowledge Retry packets. Retry packets include the packet +number from the Initial packet it responds to. Version Negotiation packets +cannot be acknowledged because they do not contain a packet number. Rather than +relying on ACK frames, these packets are implicitly acknowledged by the next +Initial packet sent by the client. An ACK frame is shown below. From d6d9837d685d3de4d035a78fa7c99bc03e99e8ba Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Wed, 25 Apr 2018 12:30:59 +0200 Subject: [PATCH 15/18] Restore some of the endpoint-agnosticism that got lost in rebasing --- draft-ietf-quic-transport.md | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index a7bf765b70..11b03bc5c0 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -1766,26 +1766,28 @@ restart the alarm for a longer period of time. ### Privacy Implications of Connection Migration {#migration-linkability} Using a stable connection ID on multiple network paths allows a passive observer -to correlate activity between those paths. A client that moves between networks -might not wish to have their activity correlated by any entity other than a -server. The NEW_CONNECTION_ID message can be sent by a server to provide an -unlinkable connection ID for use in case the client wishes to explicitly break +to correlate activity between those paths. An endpoint that moves between +networks might not wish to have their activity correlated by any entity other +than their peer. The NEW_CONNECTION_ID message can be sent to provide an +unlinkable connection ID for use in case a peer wishes to explicitly break linkability between two points of network attachment. An endpoint that does not require the use of a connection ID should not request that its peer use a connection ID. Such an endpoint does not need to provide new connection IDs using the NEW_CONNECTION_ID frame. -A client might need to send packets on multiple networks without receiving any -response from the server. To ensure that the client is not linkable across each -of these changes, a new connection ID is needed for each network. To support -this, a server sends multiple NEW_CONNECTION_ID messages. Each +An endpoint might need to send packets on multiple networks without receiving +any response from its peer. To ensure that the endpoint is not linkable across +each of these changes, a new connection ID is needed for each network. To +support this, multiple NEW_CONNECTION_ID messages are needed. Each NEW_CONNECTION_ID is marked with a sequence number. Connection IDs MUST be used in the order in which they are numbered. -A client which wishes to break linkability upon changing networks MUST use the -connection ID provided by the server. Protection of packet numbers ensures that -packet numbers cannot be used to correlate connections. +An endpoint that to break linkability upon changing networks MUST use a +previously unused connection ID provided by its peer. Protection of packet +numbers ensures that packet numbers cannot be used to correlate connections. +Other properties of packets, such as timing and size, might be used to correlate +activity, but no explicit correlation can be used to link activity across paths. Clients MAY change connection ID at any time based on implementation-specific concerns. For example, after a period of network inactivity NAT rebinding might From a1c4d41f7110eedb5536bab02b1d927cc01b68c8 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Wed, 25 Apr 2018 12:32:52 +0200 Subject: [PATCH 16/18] Grammar boobo --- draft-ietf-quic-transport.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index 11b03bc5c0..b3276f6625 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -346,7 +346,7 @@ Packet Number: : The Packet Number is a 32-bit field that follows the two connection IDs. {{packet-numbers}} describes the use of packet numbers. Packet numbers are - protected separate to the packet payload. + protected separately to the packet payload. Payload: From 8e7540f9ace4075ad0a3886944779b6ad8039958 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Thu, 3 May 2018 12:37:33 +1000 Subject: [PATCH 17/18] Addressing nits from final review --- draft-ietf-quic-tls.md | 10 +++++----- draft-ietf-quic-transport.md | 16 +++++++++------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index c9753ef75f..35dd5e6944 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -866,9 +866,9 @@ 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 encryption -({{pn-encrypt}}). Thus, the unprotected packet number is part of the AAD. When -removing packet protection, an endpoint first removes the protection from the -packet number. +({{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. All QUIC packets other than Version Negotiation and Stateless Reset packets are protected with an AEAD algorithm {{!AEAD}}. Prior to establishing a shared @@ -941,8 +941,8 @@ 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. -For packets with a long header, the ciphertext starting -immediately after the packet number is used (that is, octet 17 onwards). +For packets with a long header, the ciphertext starting immediately after the +packet number is used. For packets with a short header, the packet number length is not known before decryption, so it is assumed to be the smaller of the maximum possible packet diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index b3276f6625..4ae0b694fd 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -345,8 +345,9 @@ Payload Length: Packet Number: : The Packet Number is a 32-bit field that follows the two connection IDs. - {{packet-numbers}} describes the use of packet numbers. Packet numbers are - protected separately to the packet payload. + Packet numbers are not encrypted as part of packet protection, but instead + have additional confidentiality protection. {{packet-numbers}} describes the + use of packet numbers. Payload: @@ -454,7 +455,8 @@ Packet Number: : The length of the packet number field depends on the packet type. This field can be 1, 2 or 4 octets long depending on the short packet type. Packet - numbers are protected separate to the packet payload. + numbers are not encrypted as part of packet protection, but instead have + additional confidentiality protection. Protected Payload: @@ -696,10 +698,10 @@ continue to use the same Destination Connection ID for 0-RTT packets, see The version field for protected packets is the current QUIC version. -The packet number field contains a packet number, which is protected separately -from the rest of the packet (see {{QUIC-TLS}} for details). The underlying -packet number increases with each packet sent, see {{packet-numbers}} for -details. +The packet number field contains a packet number, which has additional +confidentiality protection that is applied after packet protection is applied +(see {{QUIC-TLS}} for details). The underlying packet number increases with +each packet sent, see {{packet-numbers}} for details. The payload is protected using authenticated encryption. {{QUIC-TLS}} describes packet protection in detail. After decryption, the plaintext consists of a From 947db7f42e392d3db77d6ee68ef7f4c0d74a6247 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Thu, 3 May 2018 14:22:51 +1000 Subject: [PATCH 18/18] Remove confusion without changing the design --- draft-ietf-quic-tls.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index 35dd5e6944..7b69f43d8e 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -944,8 +944,8 @@ encryption algorithm. For packets with a long header, the ciphertext starting immediately after the packet number is used. -For packets with a short header, the packet number length is not known before -decryption, so it is assumed to be the smaller of the maximum possible packet +For packets with a short header, the packet number length is +assumed to be the smaller of the maximum possible packet number encoding (4 octets), or the size of the protected packet minus the minimum expansion for the AEAD. Thus, the sampled ciphertext for a short header can be determined by: