From 867af94790a3e2cb696dadca9352d7bff537e37a Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Fri, 21 Dec 2018 12:10:15 +1100 Subject: [PATCH 01/18] Rework Key Update This section was pretty old and it had at least one bug, along with a bunch of editorial lack of clarity. Substantively, this does two things: 1. It specifies what label to use for the KDF when updating. The agreement at one time was that we would use a quic-specific label, but that never really got captured properly. This proposes "quic ku". 2. It specifies that acknowledgments of packets with a given key phase are necessary before another update can be triggered. As noted in #2214, simultaneous updates can result in a deadlock if updates happen too quickly. This has the nice effect of allowing update compliance to be more rigorously tested. Closes #2214. --- draft-ietf-quic-tls.md | 92 ++++++++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 35 deletions(-) diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index 18f515a028..60e2697640 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -1098,50 +1098,23 @@ anticipation of receiving a ClientHello. # Key Update Once the 1-RTT keys are established and the short header is in use, it is -possible to update the keys. The KEY_PHASE bit in the short header is used to -indicate whether key updates have occurred. The KEY_PHASE bit is initially set -to 0 and then inverted with each key update. +possible to update the keys used to protect packets. The KEY_PHASE bit in the +short header is used to indicate whether key updates have occurred. The +KEY_PHASE bit is initially set to 0 and then inverted with each key update. The KEY_PHASE bit allows a recipient to detect a change in keying material -without necessarily needing to receive the first packet that triggered the -change. An endpoint that notices a changed KEY_PHASE bit can update keys and -decrypt the packet that contains the changed bit. +without needing to receive the first packet that triggered the change. An +endpoint that notices a changed KEY_PHASE bit can update keys and decrypt the +packet that contains the changed bit. This mechanism replaces the TLS KeyUpdate message. Endpoints MUST NOT send a TLS KeyUpdate message. Endpoints MUST treat the receipt of a TLS KeyUpdate message as a connection error of type 0x10a, equivalent to a fatal TLS alert of unexpected_message (see {{tls-errors}}). -An endpoint MUST NOT initiate more than one key update at a time. A new key -cannot be used until the endpoint has received and successfully decrypted a -packet with a matching KEY_PHASE. - -A receiving endpoint detects an update when the KEY_PHASE bit does not match -what it is expecting. It creates a new secret (see Section 7.2 of {{!TLS13}}) -and the corresponding read key and IV using the KDF function provided by TLS. -The header protection key is not updated. - -If the packet can be decrypted and authenticated using the updated key and IV, -then the keys the endpoint uses for packet protection are also updated. The -next packet sent by the endpoint will then use the new keys. - -An endpoint does not always need to send packets when it detects that its peer -has updated keys. The next packet that it sends will simply use the new keys. -If an endpoint detects a second update before it has sent any packets with -updated keys, it indicates that its peer has updated keys twice without awaiting -a reciprocal update. An endpoint MUST treat consecutive key updates as a fatal -error and abort the connection. - -An endpoint SHOULD retain old keys for a period of no more than three times the -Probe Timeout (PTO, see {{QUIC-RECOVERY}}). After this period, old keys and -their corresponding secrets SHOULD be discarded. Retaining keys allow endpoints -to process packets that were sent with old keys and delayed in the network. -Packets with higher packet numbers always use the updated keys and MUST NOT be -decrypted with old keys. - -This ensures that once the handshake is complete, packets with the same +This process ensures that once the handshake is complete, packets with the same KEY_PHASE will have the same packet protection keys, unless there are multiple -key updates in a short time frame succession and significant packet reordering. +key updates in short succession and significant packet reordering. ~~~ Initiating Peer Responding Peer @@ -1157,12 +1130,61 @@ key updates in a short time frame succession and significant packet reordering. ~~~ {: #ex-key-update title="Key Update"} + +## Initiating Key Update + +Endpoints maintain separate read and write secrets for packet protection. An +endpoint initiates a key update by updating its packet protection write secret +and using that to protect new packets. The endpoint creates a new write secret +from the existing write secret as performed in Section 7.2 of {{!TLS13}}. This +uses the KDF function provided by TLS with a label of "quic ku". The +corresponding key and IV are created from that secret as defined in +{{protection-keys}}. The header protection key is not updated. + +The endpoint uses the key and IV to protect all subsequent packets, and inverts +the value of the KEY_PHASE bit to signal the change of keys. + +An endpoint MUST NOT initiate more than one key update at a time. A new key +cannot be used until the endpoint has received an acknowledgment for a packet it +sends with the new keys. An endpoint that receives a packet protected with old +keys that includes an acknowledgement for a packet protected with newer keys MAY +treat that as a connection error of type PROTOCOL_VIOLATION. + + +## Responding to a Key Update + +A receiving endpoint detects an update when the KEY_PHASE bit does not match +what it is expecting. The endpoint creates a new read secret and the +corresponding read key and IV using the same process as its peer. + +If the packet can be decrypted and authenticated using the updated key and IV, +then the keys the endpoint uses for packet protection (the write secret) are +also updated using the same KDF and label as for the read secret. The next +packet sent by the endpoint MUST use the new packet protection keys. + +An endpoint does not always need to send packets when it detects that its peer +has updated keys. The next packet that it sends will simply use the new keys. +If an endpoint detects a second update before it has sent any packets with +updated keys, it indicates that its peer has updated keys twice without awaiting +a reciprocal update. An endpoint MUST treat consecutive key updates as a fatal +error and abort the connection. + +An endpoint SHOULD retain old read keys for a period of no more than three times +the Probe Timeout (PTO, see {{QUIC-RECOVERY}}). After this period, old read +keys and their corresponding secrets SHOULD be discarded. Retaining keys allows +endpoints to process packets that were sent with old keys and delayed in the +network. Packets with higher packet numbers always use the updated keys and +MUST NOT be decrypted with old keys. + A packet that triggers a key update could arrive after successfully processing a packet with a higher packet number. This is only possible if there is a key compromise and an attack, or if the peer is incorrectly reverting to use of old keys. Because the latter cannot be differentiated from an attack, an endpoint MUST immediately terminate the connection if it detects this condition. + +## Key Update Frequency + In deciding when to update keys, endpoints MUST NOT exceed the limits for use of specific keys, as described in Section 5.5 of {{!TLS13}}. From b4ddb7f6a837e0771307519ae6604facf2dba5b4 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Fri, 21 Dec 2018 16:41:54 +1100 Subject: [PATCH 02/18] Switch to a two-bit key phase --- draft-ietf-quic-tls.md | 56 ++++++++++++++++++++---------------- draft-ietf-quic-transport.md | 22 +++++++------- 2 files changed, 43 insertions(+), 35 deletions(-) diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index 60e2697640..aa3a31202d 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -861,7 +861,7 @@ 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. +bits are also protected for packets with a short header. The same header protection key is used for the duration of the connection, with the value not changing after a key update (see {{key-update}}). This allows @@ -1098,13 +1098,13 @@ anticipation of receiving a ClientHello. # Key Update Once the 1-RTT keys are established and the short header is in use, it is -possible to update the keys used to protect packets. The KEY_PHASE bit in the -short header is used to indicate whether key updates have occurred. The -KEY_PHASE bit is initially set to 0 and then inverted with each key update. +possible to update the keys used to protect packets. The Key Phase bits in the +short header are used to indicate whether key updates have occurred. The +Key Phase is initially set to 0 and then incremented with each key update. -The KEY_PHASE bit allows a recipient to detect a change in keying material +The Key Phase allows a recipient to detect a change in keying material without needing to receive the first packet that triggered the change. An -endpoint that notices a changed KEY_PHASE bit can update keys and decrypt the +endpoint that notices a changed Key Phase bit can update keys and decrypt the packet that contains the changed bit. This mechanism replaces the TLS KeyUpdate message. Endpoints MUST NOT send a @@ -1113,7 +1113,7 @@ message as a connection error of type 0x10a, equivalent to a fatal TLS alert of unexpected_message (see {{tls-errors}}). This process ensures that once the handshake is complete, packets with the same -KEY_PHASE will have the same packet protection keys, unless there are multiple +Key Phase will have the same packet protection keys, unless there are multiple key updates in short succession and significant packet reordering. ~~~ @@ -1131,7 +1131,7 @@ key updates in short succession and significant packet reordering. {: #ex-key-update title="Key Update"} -## Initiating Key Update +## Initiating a Key Update Endpoints maintain separate read and write secrets for packet protection. An endpoint initiates a key update by updating its packet protection write secret @@ -1141,22 +1141,30 @@ uses the KDF function provided by TLS with a label of "quic ku". The corresponding key and IV are created from that secret as defined in {{protection-keys}}. The header protection key is not updated. -The endpoint uses the key and IV to protect all subsequent packets, and inverts -the value of the KEY_PHASE bit to signal the change of keys. +The endpoint uses the key and IV to protect all subsequent packets, and +increments the value of the Key Phase bits modulo 4 in the short packet header +to signal the change of keys. An endpoint MUST NOT initiate more than one key update at a time. A new key -cannot be used until the endpoint has received an acknowledgment for a packet it -sends with the new keys. An endpoint that receives a packet protected with old -keys that includes an acknowledgement for a packet protected with newer keys MAY -treat that as a connection error of type PROTOCOL_VIOLATION. +cannot be used until the endpoint has received an indication that its peer is +using the same key phase. + +An endpoint that receives a packet protected with old keys that includes an +acknowledgement for a packet protected with newer keys MAY treat that as a +connection error of type PROTOCOL_VIOLATION. ## Responding to a Key Update -A receiving endpoint detects an update when the KEY_PHASE bit does not match +A receiving endpoint detects an update when the Key Phase is one greater than what it is expecting. The endpoint creates a new read secret and the corresponding read key and IV using the same process as its peer. +A packet with a Key Phase other than the expected or next value MUST be +discarded. However, endpoints MUST NOT generate a timing side-channel signal +that might indicate that this specific field was invalid (see +{{header-protect-analysis}}). + If the packet can be decrypted and authenticated using the updated key and IV, then the keys the endpoint uses for packet protection (the write secret) are also updated using the same KDF and label as for the read secret. The next @@ -1362,15 +1370,15 @@ 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 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 header protection removal, packet number recovery, and -packet protection removal MUST be applied together without timing and other -side-channels. +An attacker could guess values for packet numbers or key phase 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 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 packet numbers MUST be free from side-channels that would reveal the packet diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index d68f8895af..470d529817 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -3480,7 +3480,7 @@ 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|1|S|R|R|K|P P| +|0|1|S|R| K | P | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Destination Connection ID (0..144) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -3510,19 +3510,19 @@ Spin Bit (S): Reserved Bits (R): -: 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. +: The next bit (0x10) of byte 0 is reserved. This bit is 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 this bit after removing protection as a connection + error of type PROTOCOL_VIOLATION. Key Phase (K): -: 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}}). +: The next two bits (those with a mask of 0x0c) of byte 0 indicate 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. + These bits are protected using header protection (see Section 5.4 of + {{QUIC-TLS}}). Packet Number Length (P): From 4d3f65aacb02e09cb9b4e0ca2f4d5b9c6adeb373 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Fri, 21 Dec 2018 16:45:15 +1100 Subject: [PATCH 03/18] unplural --- 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 470d529817..07efd8e879 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -3508,7 +3508,7 @@ Spin Bit (S): : The sixth bit (0x20) of byte 0 is the Latency Spin Bit, set as described in {{!SPIN=I-D.ietf-quic-spin-exp}}. -Reserved Bits (R): +Reserved Bit (R): : The next bit (0x10) of byte 0 is reserved. This bit is protected using header protection (see Section 5.4 of {{QUIC-TLS}}). The value included prior to From 4836c87e3b4317e847547101835ad96633f328a3 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Mon, 24 Dec 2018 17:46:43 +1100 Subject: [PATCH 04/18] Review comments --- draft-ietf-quic-tls.md | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index aa3a31202d..0a45645b4d 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -1100,12 +1100,13 @@ anticipation of receiving a ClientHello. Once the 1-RTT keys are established and the short header is in use, it is possible to update the keys used to protect packets. The Key Phase bits in the short header are used to indicate whether key updates have occurred. The -Key Phase is initially set to 0 and then incremented with each key update. +Key Phase is initially set to 0 and then incremented modulo 4 with each key +update. The Key Phase allows a recipient to detect a change in keying material without needing to receive the first packet that triggered the change. An -endpoint that notices a changed Key Phase bit can update keys and decrypt the -packet that contains the changed bit. +endpoint that notices a changed Key Phase updates keys and decrypts the packet +that contains the changed value. This mechanism replaces the TLS KeyUpdate message. Endpoints MUST NOT send a TLS KeyUpdate message. Endpoints MUST treat the receipt of a TLS KeyUpdate @@ -1142,8 +1143,8 @@ corresponding key and IV are created from that secret as defined in {{protection-keys}}. The header protection key is not updated. The endpoint uses the key and IV to protect all subsequent packets, and -increments the value of the Key Phase bits modulo 4 in the short packet header -to signal the change of keys. +increments the value of the Key Phase modulo 4 in the short packet header to +signal the change of keys. An endpoint MUST NOT initiate more than one key update at a time. A new key cannot be used until the endpoint has received an indication that its peer is @@ -1160,9 +1161,18 @@ A receiving endpoint detects an update when the Key Phase is one greater than what it is expecting. The endpoint creates a new read secret and the corresponding read key and IV using the same process as its peer. -A packet with a Key Phase other than the expected or next value MUST be -discarded. However, endpoints MUST NOT generate a timing side-channel signal -that might indicate that this specific field was invalid (see +A packet with a Key Phase other than the expected or next two values MUST be +discarded, unless the packet number is smaller than the lowest packet number +received with the current keys. Old keys can be used to remove protection with +lower-numbered packets. + +Allowing for two increments is necessary in the case where both endpoints +simultaneously update keys. If one endpoint updates when it sees the change and +all packets it sends from the first update are lost, then a gap in Key Phase +will be observed by its peer. + +In all cases, endpoints MUST NOT generate a timing side-channel signal that +might indicate that this specific field was invalid (see {{header-protect-analysis}}). If the packet can be decrypted and authenticated using the updated key and IV, From a2ef7224f97218680dc5b5cdf607834c3772370b Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Thu, 10 Jan 2019 08:29:53 +1100 Subject: [PATCH 05/18] Changes from review comments --- draft-ietf-quic-tls.md | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index bd84a8226e..14ed4b7d35 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -1102,13 +1102,13 @@ anticipation of receiving a ClientHello. Once the 1-RTT keys are established and the short header is in use, it is possible to update the keys used to protect packets. The Key Update field in the -short header are used to indicate when key updates are permitted and when they +short header is used to indicate when key updates are permitted and when they have occurred. -The the low bit of the Key Update field (0x04) is the Key Phase bit. The Key -Phase is used to indicate which packet protection keys are in use. The Key -Phase bit is initially set to 0 for the first set of 1-RTT packets. The Key -Phase is toggled to signal each key update. +The low bit of the Key Update field (0x04) is the Key Phase bit. The Key Phase +is used to indicate which packet protection keys are used to protect the packet. +The Key Phase bit is initially set to 0 for the first set of 1-RTT packets. The +Key Phase is toggled to signal each key update. The Key Phase bit allows a recipient to detect a change in keying material without needing to receive the first packet that triggered the change. An @@ -1137,17 +1137,19 @@ and @N. Values in brackets [] indicate the value of Key Update bits. Initiating Peer Responding Peer @M [10] QUIC Packets -. Update to @N -@N [01] QUIC Packets --------> QUIC Packets [10] @M - Update to @N . + <-------- +... Update to @N +@N [01] QUIC Packets + --------> + Update to @N ... QUIC Packets [11] @N <-------- -. Key Update Permitted +... Key Update Permitted @N [11] QUIC Packets --------> - Key Update Permitted . + Key Update Permitted ... ~~~ {: #ex-key-update title="Key Update"} @@ -1162,13 +1164,14 @@ uses the KDF function provided by TLS with a label of "quic ku". The corresponding key and IV are created from that secret as defined in {{protection-keys}}. The header protection key is not updated. -The endpoint uses the key and IV to protect all subsequent packets, clears the -Key Update Permitted bit, and toggles the value of the low Key Phase bit. +The endpoint clears the Key Update Permitted bit, and toggles the value of the +low Key Phase bit, and uses the updated key and IV to protect all subsequent +packets. -An endpoint MUST NOT initiate more than one key update at a time. A new key -cannot be used until the endpoint has successfully processed a packet with a -matching Key Phase and the Key Update Permitted bit set. Together, these -indicate that the key update was received and acted on. +An endpoint MUST NOT initiate more than one key update at a time. A subsequent +key update can only be performed after the endpoint has successfully processed a +packet with a matching Key Phase and the Key Update Permitted bit set. +Together, these indicate that the key update was received and acted on. Once an endpoint has received and successfully processed packets with the same Key Phase value, this indicates that the peer has also updated keys. The @@ -1199,7 +1202,7 @@ receiving. If the packet protection is successfully removed using the updated key and IV, then the keys the endpoint initiates a key update in response, as described in {{key-update-initiate}}. However, as packets with a matching Key Phase have -been received, the Key Update Permitted bit MAY be set to 1 on the next packet +been received, the Key Update Permitted bit can be set to 1 on the next packet it sends. An endpoint does not always need to send packets when it detects that its peer @@ -1228,7 +1231,9 @@ An endpoint SHOULD retain old read keys for a period of no more than three times the Probe Timeout (PTO, see {{QUIC-RECOVERY}}). After this period, old read keys and their corresponding secrets SHOULD be discarded. An endpoint MAY keep the Key Update Permitted bit set to 0 until it discards old read keys to limit -the number of keys it maintains. +the number of keys it maintains. An endpoint MAY also prevent key update until +it discards keys from the handshake, including any 0-RTT keys. An endpoint +SHOULD set the Key Update Permitted bit when possible. Endpoints MUST NOT generate a timing side-channel signal that might indicate that the Key Update field was invalid (see {{header-protect-analysis}}). From d62829d76d18807be535838d0b986c265d61f0a5 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Thu, 10 Jan 2019 08:31:45 +1100 Subject: [PATCH 06/18] Fix sudden missing reference problem --- 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 14ed4b7d35..b1730d536b 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -1098,7 +1098,7 @@ TLS ClientHello. The server MAY retain these packets for later decryption in anticipation of receiving a ClientHello. -# Key Update +# Key Update {#key-update} Once the 1-RTT keys are established and the short header is in use, it is possible to update the keys used to protect packets. The Key Update field in the @@ -1131,7 +1131,7 @@ message as a connection error of type 0x10a, equivalent to a fatal TLS alert of unexpected_message (see {{tls-errors}}). {{ex-key-update}} shows a key update process, with keys used identified with @M -and @N. Values in brackets [] indicate the value of Key Update bits. +and @N. Values in brackets \[] indicate the value of Key Update bits. ~~~ Initiating Peer Responding Peer From e9bb544b9b84cea909ab0c98cea28f6839cc6bf4 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Thu, 10 Jan 2019 08:57:51 +1100 Subject: [PATCH 07/18] Disallow reneging on Key Update Permitted --- draft-ietf-quic-tls.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index b1730d536b..27f1ca8b51 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -1115,7 +1115,6 @@ without needing to receive the first packet that triggered the change. An endpoint that notices a changed Key Phase updates keys and decrypts the packet that contains the changed value. - The high bit of the Key Update field (0x08) is the Key Update Permitted bit. Endpoints set this value to 0 until they successfully process a packet with keys from the same key phase as they are using to send. An endpoint MUST NOT @@ -1229,11 +1228,17 @@ MUST treat this as a connection error of type KEY_UPDATE_ERROR. An endpoint SHOULD retain old read keys for a period of no more than three times the Probe Timeout (PTO, see {{QUIC-RECOVERY}}). After this period, old read -keys and their corresponding secrets SHOULD be discarded. An endpoint MAY keep -the Key Update Permitted bit set to 0 until it discards old read keys to limit -the number of keys it maintains. An endpoint MAY also prevent key update until -it discards keys from the handshake, including any 0-RTT keys. An endpoint -SHOULD set the Key Update Permitted bit when possible. +keys and their corresponding secrets SHOULD be discarded. + +An endpoint MAY keep the Key Update Permitted bit set to 0 until it discards old +read keys to limit the number of keys it maintains. An endpoint MAY also +prevent key update until it discards keys from the handshake, including any +0-RTT keys. An endpoint SHOULD set the Key Update Permitted bit when possible. + +Once set, the Key Update Permitted bit MUST NOT be cleared for packets protected +with the same keys. An endpoint MAY treat receipt of a packet with the Key +Update Permitted bit cleared as a connection error of type KEY_UPDATE_ERROR if +the bit was previously set on packets protected with the same keys. Endpoints MUST NOT generate a timing side-channel signal that might indicate that the Key Update field was invalid (see {{header-protect-analysis}}). From acff3b6afb460f447ca4232f0218f9c83d4adc97 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Thu, 10 Jan 2019 09:33:38 +1100 Subject: [PATCH 08/18] Make key update optional The important change here is to explicitly permit blocking of key updates. However, it does not remove the encouragement for enabling them. That seems to be the right sort of balance: we can't force implementations to support updates, though it's still a good idea to do so. This makes more extensive changes to support better text in the updated description of Key Update Permitted. Formalizing "key phase" as a concept rather than a field is the main one. --- draft-ietf-quic-tls.md | 48 ++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index 27f1ca8b51..f5102c0fba 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -863,7 +863,7 @@ 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 +this covers the reserved bits and the Packet Number Length field; the Key Update bits are also protected for packets with a short header. The same header protection key is used for the duration of the connection, with @@ -1105,21 +1105,23 @@ possible to update the keys used to protect packets. The Key Update field in the short header is used to indicate when key updates are permitted and when they have occurred. -The low bit of the Key Update field (0x04) is the Key Phase bit. The Key Phase +The low bit of the Key Update field (0x04) is the Key Phase bit. The key phase is used to indicate which packet protection keys are used to protect the packet. The Key Phase bit is initially set to 0 for the first set of 1-RTT packets. The -Key Phase is toggled to signal each key update. +key phase is toggled to signal each key update. -The Key Phase bit allows a recipient to detect a change in keying material -without needing to receive the first packet that triggered the change. An -endpoint that notices a changed Key Phase updates keys and decrypts the packet -that contains the changed value. +The key phase allows a recipient to detect a change in keying material without +needing to receive the first packet that triggered the change. An endpoint that +notices a changed key phase updates keys and decrypts the packet that contains +the changed value. -The high bit of the Key Update field (0x08) is the Key Update Permitted bit. -Endpoints set this value to 0 until they successfully process a packet with keys -from the same key phase as they are using to send. An endpoint MUST NOT -initiate a key update until it receives a packet with the Key Update Permitted -bit set. +The high bit of the Key Update field (0x08) is the Key Update Permitted bit. An +endpoint MUST NOT initiate a key update unless they have received a packet with +the current Key Phase and the Key Update Permitted bit set to 1. An endpoint +MAY keep this value set to 0, forbidding key updates. An endpoint MUST NOT set +this value to 1 until it successfully processes a packet with keys from the same +key phase. Once this bit is set it MUST NOT be cleared for packets in the same +key phase. Only packets that increase the largest received packet number are used to trigger key updates or changes in the Key Update Permitted bit. @@ -1164,20 +1166,20 @@ corresponding key and IV are created from that secret as defined in {{protection-keys}}. The header protection key is not updated. The endpoint clears the Key Update Permitted bit, and toggles the value of the -low Key Phase bit, and uses the updated key and IV to protect all subsequent +Key Phase bit, and uses the updated key and IV to protect all subsequent packets. An endpoint MUST NOT initiate more than one key update at a time. A subsequent key update can only be performed after the endpoint has successfully processed a -packet with a matching Key Phase and the Key Update Permitted bit set. +packet with a matching key phase and the Key Update Permitted bit set. Together, these indicate that the key update was received and acted on. Once an endpoint has received and successfully processed packets with the same -Key Phase value, this indicates that the peer has also updated keys. The +key phase, this indicates that the peer has also updated keys. The endpoint can then set the Key Update Permitted bit to 1 on packets it subsequently sends. An endpoint MUST NOT set Key Update Permitted to 1 on packets it sends unless it has successfully processed packets with a matching -Key Phase. An endpoint MAY defer setting Key Update Permitted to 1 until it has +key phase. An endpoint MAY defer setting Key Update Permitted to 1 until it has discarded old keys, see {{key-update-old-keys}}. Using Key Update Permitted in this manner guarantees at least one round trip @@ -1192,7 +1194,7 @@ connection error of type KEY_UDPATE_ERROR. ## Responding to a Key Update An endpoint that sets Key Update Permitted to 1 on packets it sends is willing -to accept key updates. If a packet is received with a Key Phase that differs +to accept key updates. If a packet is received with a key phase that differs from the value the endpoint expects, the endpoint creates a new packet protection secret for reading and the corresponding key and IV. The endpoint uses the same key derivation process as its peer uses to generate keys for @@ -1200,7 +1202,7 @@ receiving. If the packet protection is successfully removed using the updated key and IV, then the keys the endpoint initiates a key update in response, as described in -{{key-update-initiate}}. However, as packets with a matching Key Phase have +{{key-update-initiate}}. However, as packets with a matching key phase have been received, the Key Update Permitted bit can be set to 1 on the next packet it sends. @@ -1215,7 +1217,7 @@ connection error of type KEY_UDPATE_ERROR. ## Using Old Keys {#key-update-old-keys} If the most recent packet sent by the endpoint contained a Key Update Permitted -bit set to 0, a Key Phase other than the value expected indicates that the +bit set to 0, a key phase other than the value expected indicates that the packet was protected with old keys. If those old keys are available, then they can be used to remove packet protection. @@ -1235,10 +1237,10 @@ read keys to limit the number of keys it maintains. An endpoint MAY also prevent key update until it discards keys from the handshake, including any 0-RTT keys. An endpoint SHOULD set the Key Update Permitted bit when possible. -Once set, the Key Update Permitted bit MUST NOT be cleared for packets protected -with the same keys. An endpoint MAY treat receipt of a packet with the Key -Update Permitted bit cleared as a connection error of type KEY_UPDATE_ERROR if -the bit was previously set on packets protected with the same keys. +Once set, the Key Update Permitted bit MUST NOT be cleared for packets with the +same key phase. An endpoint MAY treat receipt of a packet with the Key Update +Permitted bit cleared as a connection error of type KEY_UPDATE_ERROR if the bit +was previously set on packets protected with the same keys. Endpoints MUST NOT generate a timing side-channel signal that might indicate that the Key Update field was invalid (see {{header-protect-analysis}}). From e378a885781b04b50bbae624d9a8cd601162353b Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Wed, 13 Feb 2019 12:13:11 +1100 Subject: [PATCH 09/18] KEYS_READY frame This frame solves several problems. 1. it allows us to get rid of Initial keys very quickly, without relying on the existing implicit mess. 2. it allows us to get rid of Handshake keys quickly, without timers. 3. it allows us to regulate the rate of key update, without risk of becoming unsynchronized. The big design question here is whether to include an explicit marker for the current key phase, or to pull that in from the packet. I've chosen the latter, but I am willing to be convinced that this is a bad idea. There is a risk that retransmissions of KEYS_READY will cause problems, but that risk is easily addressed by purging unacknowledged KEYS_READY frames any time you initiate a key update. Or, you could not retransmit frames blindly. The alternative means pulling in the notion of an epoch, likely copying from DTLS (0=Initial, 1=0-RTT, 2=Handshake, 3+=1-RTT). Thats complicated and we would still need to work out what to do with the validation code in that case. I've tried to keep the request to minimize the number of active keys, by allowing KEYS_READY to be deferred by up to 3PTO. That seems to work well. Closes #2267, #1951. Prerequisite for fixing #2309. --- draft-ietf-quic-tls.md | 116 ++++++++++++++++------------------- draft-ietf-quic-transport.md | 58 +++++++++++++++--- 2 files changed, 103 insertions(+), 71 deletions(-) diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index 918488c764..a5e3c25810 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -1118,7 +1118,7 @@ message as a connection error of type 0x10a, equivalent to a fatal TLS alert of unexpected_message (see {{tls-errors}}). {{ex-key-update}} shows a key update process, with keys used identified with @M -and @N. Values in brackets \[] indicate the value of Key Phase bits. +and @N. Values in brackets \[] indicate the value of Key Phase bit. ~~~ Initiating Peer Responding Peer @@ -1155,87 +1155,75 @@ uses the KDF function provided by TLS with a label of "quic ku". The corresponding key and IV are created from that secret as defined in {{protection-keys}}. The header protection key is not updated. -The endpoint clears the Key Update Permitted bit, and toggles the value of the -Key Phase bit, and uses the updated key and IV to protect all subsequent -packets. +The endpoint toggles the value of the Key Phase bit, and uses the updated key +and IV to protect all subsequent packets. -An endpoint MUST NOT initiate more than one key update at a time. A subsequent -key update can only be performed after the endpoint has successfully processed a -packet with a matching key phase and the Key Update Permitted bit set. -Together, these indicate that the key update was received and acted on. +An endpoint MUST NOT initiate a key update prior to having received a KEYS_READY +frame in a packet from the current key phase. A subsequent key update can only +be performed after the endpoint has successfully processed a KEYS_READY frame +from a packet with a matching key phase. This ensures that keys are available +to both peers before another can be initiated. -Once an endpoint has received and successfully processed packets with the same -key phase, this indicates that the peer has also updated keys. The -endpoint can then set the Key Update Permitted bit to 1 on packets it -subsequently sends. An endpoint MUST NOT set Key Update Permitted to 1 on -packets it sends unless it has successfully processed packets with a matching -key phase. An endpoint MAY defer setting Key Update Permitted to 1 until it has -discarded old keys, see {{key-update-old-keys}}. - -Using Key Update Permitted in this manner guarantees at least one round trip -between updates, preventing multiple updates that could result in endpoints -being unable to process any packets. - -An endpoint that receives a packet protected with old keys that includes an -acknowledgement for a packet protected with newer keys MAY treat that as a -connection error of type KEY_UDPATE_ERROR. +Once an endpoint has successfully processed a packet with the same key phase, it +can send a KEYS_READY frame. Endpoints MAY defer sending a KEYS_READY frame +after a key update (see {{key-update-old-keys}}). ## Responding to a Key Update -An endpoint that sets Key Update Permitted to 1 on packets it sends is willing -to accept key updates. If a packet is received with a key phase that differs -from the value the endpoint expects, the endpoint creates a new packet -protection secret for reading and the corresponding key and IV. The endpoint -uses the same key derivation process as its peer uses to generate keys for -receiving. +An endpoint that sends a KEYS_READY frame can accept further key updates. A key +update can happen even without seeing a KEYS_READY frame from the peer. If a +packet is received with a key phase that differs from the value the endpoint +used to protect the packet containing its last KEYS_READY frame, the endpoint +creates a new packet protection secret for reading and the corresponding key and +IV. An endpoint uses the same key derivation process as its peer uses to +generate keys for receiving. If the packet protection is successfully removed using the updated key and IV, then the keys the endpoint initiates a key update in response, as described in -{{key-update-initiate}}. However, as packets with a matching key phase have -been received, the Key Update Permitted bit can be set to 1 on the next packet -it sends. +{{key-update-initiate}}. An endpoint that responds to a key update MUST send a +KEYS_READY frame to indicate that it is both sending and receiving with updated +keys, though it MAY defer sending the frame (see {{key-update-old-keys}}). An endpoint does not always need to send packets when it detects that its peer -has updated keys. The next packet that it sends will simply use the new keys. -If an endpoint detects a second update before it has sent any packets with -updated keys, it indicates that its peer has updated keys twice without awaiting -a reciprocal update. An endpoint MUST treat consecutive key updates as a -connection error of type KEY_UDPATE_ERROR. +has updated keys. The next packet that it sends use the new keys and include +the KEYS_READY frame. If an endpoint detects a second update before it has sent +any packets with updated keys or a KEYS_READY frame, it indicates that its peer +has updated keys twice without awaiting a reciprocal update. An endpoint MUST +treat consecutive key updates as a connection error of type KEY_UPDATE_ERROR. + +Endpoints responding to an apparent key update MUST NOT generate a timing +side-channel signal that might indicate that the Key Phase bit was invalid (see +{{header-protect-analysis}}). Endpoints can use dummy packet protection keys in +place of discarded keys when key updates are not permitted. ## Using Old Keys {#key-update-old-keys} -If the most recent packet sent by the endpoint contained a Key Update Permitted -bit set to 0, a key phase other than the value expected indicates that the -packet was protected with old keys. If those old keys are available, then they -can be used to remove packet protection. +During a key update, packets protected with older keys might arrive if they were +delayed by the network. If those old keys are available, then they can be used +to remove packet protection. -Old keys might be used to remove protection from packets that were are reordered -in the network. However, it is never valid for old keys to be used to protect -packets with packets that have higher packet numbers than packets that were -protected with newer keys. An endpoint that successfully removes protection -with old keys when newer keys were used for packets with lower packet numbers -MUST treat this as a connection error of type KEY_UPDATE_ERROR. +After a key update, an endpoint MAY delay sending the KEYS_READY frame by up to +three times the Probe Timeout (PTO, see {{QUIC-RECOVERY}}) to minimize the +number of active keys it maintains. During this time, an endpoint can use old +keys to process delayed packets rather than enabling a new key update. This +only applies to key updates that use the Key Phase bit; endpoints MUST NOT defer +sending of KEYS_READY during and immediately after the handshake. + +Even if old keys are available, those keys MUST NOT be used to protect packets +with packets that have higher packet numbers than packets that were protected +with newer keys. An endpoint that successfully removes protection with old keys +when newer keys were used for packets with lower packet numbers MUST treat this +as a connection error of type KEY_UPDATE_ERROR. An endpoint SHOULD retain old read keys for a period of no more than three times -the Probe Timeout (PTO, see {{QUIC-RECOVERY}}). After this period, old read -keys and their corresponding secrets SHOULD be discarded. - -An endpoint MAY keep the Key Update Permitted bit set to 0 until it discards old -read keys to limit the number of keys it maintains. An endpoint MAY also -prevent key update until it discards keys from the handshake, including any -0-RTT keys. An endpoint SHOULD set the Key Update Permitted bit when possible. - -Once set, the Key Update Permitted bit MUST NOT be cleared for packets with the -same key phase. An endpoint MAY treat receipt of a packet with the Key Update -Permitted bit cleared as a connection error of type KEY_UPDATE_ERROR if the bit -was previously set on packets protected with the same keys. - -Endpoints MUST NOT generate a timing side-channel signal that might indicate -that the Key Update field was invalid (see {{header-protect-analysis}}). -Endpoints can use dummy packet protection keys in place of discarded keys when -key updates are not permitted. +the current PTO. After this period, old read keys and their corresponding +secrets SHOULD be discarded. + +An endpoint that receives a packet protected with old keys that includes an +acknowledgement for a packet protected with newer keys MAY treat that as a +connection error of type KEY_UPDATE_ERROR. ## Key Update Frequency diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index db9938f4bf..fd988af089 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -2821,6 +2821,7 @@ frames are explained in more detail in {{frame-formats}}. | 0x1a | PATH_CHALLENGE | {{frame-path-challenge}} | | 0x1b | PATH_RESPONSE | {{frame-path-response}} | | 0x1c - 0x1d | CONNECTION_CLOSE | {{frame-connection-close}} | +| 0x1e | KEYS_READY | {{frame-keys-ready}} | {: #frame-types title="Frame Types"} All QUIC frames are idempotent in this version of QUIC. That is, a valid @@ -3035,6 +3036,9 @@ containing that information is acknowledged. * PING and PADDING frames contain no information, so lost PING or PADDING frames do not require repair. +* KEYS_READY frames are sent until acknowledged or until newer keys are used for + sending packets. + Endpoints SHOULD prioritize retransmission of data over sending new data, unless priorities specified by the application indicate otherwise (see {{stream-prioritization}}). @@ -3700,12 +3704,12 @@ and will contain a CRYPTO frame with an offset matching the size of the CRYPTO frame sent in the first Initial packet. Cryptographic handshake messages subsequent to the first do not need to fit within a single UDP datagram. + #### Abandoning Initial Packets {#discard-initial} -A client stops both sending and processing Initial packets when it sends its -first Handshake packet. A server stops sending and processing Initial packets -when it receives its first Handshake packet. Though packets might still be in -flight or awaiting acknowledgment, no further Initial packets need to be +Endpoints cease both sending and processing Initial packets when it receives a +Handshake packet containing a KEYS_READY frame. Though packets might still be +in flight or awaiting acknowledgment, no further Initial packets need to be exchanged beyond this point. Initial packet protection keys are discarded (see Section 4.10 of {{QUIC-TLS}}) along with any loss recovery and congestion control state (see Sections 5.3.1.2 and 6.9 of {{QUIC-RECOVERY}}). @@ -3713,6 +3717,7 @@ control state (see Sections 5.3.1.2 and 6.9 of {{QUIC-RECOVERY}}). Any data in CRYPTO frames is discarded - and no longer retransmitted - when Initial keys are discarded. + ### 0-RTT {#packet-0rtt} A 0-RTT packet uses long headers with a type value of 0x1, followed by the @@ -3821,8 +3826,10 @@ ACK frames. Handshake packets MAY contain CONNECTION_CLOSE frames. Endpoints MUST treat receipt of Handshake packets with other frames as a connection error. Like Initial packets (see {{discard-initial}}), data in CRYPTO frames at the -Handshake encryption level is discarded - and no longer retransmitted - when -Handshake protection keys are discarded. +Handshake encryption level and the corresponding keys are discarded - and data +is no longer retransmitted - when a KEYS_READY frame is received in a 1-RTT +packet. + ### Retry Packet {#packet-retry} @@ -3936,6 +3943,7 @@ failed validation as a connection error of type TRANSPORT_PARAMETER_ERROR. A Retry packet does not include a packet number and cannot be explicitly acknowledged by a client. + ## Short Header Packets {#short-header} This version of QUIC defines a single packet type which uses the @@ -5126,7 +5134,43 @@ Reason Phrase: This SHOULD be a UTF-8 encoded string {{!RFC3629}}. -## KEYS_READY Frame {#frame- +## KEYS_READY Frame {#frame-keys-ready} + +An endpoint sends a KEYS_READY frame (type=0x1e) to signal that it has installed +keys for reading and writing packets. Receipt of this frame in a packet +indicates that all earlier keys can be safely discarded. + +The KEYS_READY frame contains no additional fields. + +The packet that carries a KEYS_READY frame determines which keys are ready. The +keys with the same key phase as those used in the packet that carries the +KEYS_READY frame are present. + +An endpoint MUST send a KEYS_READY packet in the first packet it sends using +keys, but only after having successfully processed a packet using the +corresponding keys. + +KEYS_READY frames are retransmitted when declared lost, however implementations +need to take care not to retransmit lost KEYS_READY frames if they initiate a +subsequent key update. This can happen if an acknowledgment for a packet +containing a KEYS_READY frame is lost. + +Endpoints MUST NOT send KEYS_READY frames in Initial or 0-RTT packets. + +A KEYS_READY frame used during the handshake can be used to indicate the +availability of Handshake keys by including it in a Handshake packet. An +endpoint sends this frame in its first Handshake packet. Once received, an +endpoint can discard Initial keys. + +A KEYS_READY frame used after the completion of the handshake in 1-RTT packets +indicates that Handshake keys are no longer needed. A client sends this frame +in its first 1-RTT packet, and a server sends this frame in the first packet it +sends after completing the handshake. Note that a server might send 1-RTT keys +prior to this. + +An endpoint uses the KEYS_READY frame in 1-RTT packets to indicate that it is +able to receive a key update (see Section 6 of {{QUIC-TLS}}). + ## Extension Frames From fcc1d9e7d1a2239734a9f5722c9522723218fb66 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Wed, 13 Feb 2019 12:40:36 +1100 Subject: [PATCH 10/18] Add to example flows --- draft-ietf-quic-transport.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index bea8b41e1d..6715cfc164 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -1259,14 +1259,14 @@ Client Server Initial[0]: CRYPTO[CH] -> Initial[0]: CRYPTO[SH] ACK[0] - Handshake[0]: CRYPTO[EE, CERT, CV, FIN] + Handshake[0]: KEYS_READY, CRYPTO[EE, CERT, CV, FIN] <- 1-RTT[0]: STREAM[1, "..."] Initial[1]: ACK[0] -Handshake[0]: CRYPTO[FIN], ACK[0] -1-RTT[0]: STREAM[0, "..."], ACK[0] -> +Handshake[0]: KEYS_READY, CRYPTO[FIN], ACK[0] +1-RTT[0]: KEYS_READY, STREAM[0, "..."], ACK[0] -> - 1-RTT[1]: STREAM[55, "..."], ACK[0] + 1-RTT[1]: KEYS_READY, STREAM[55, "..."], ACK[0] <- Handshake[1]: ACK[0] ~~~~ {: #tls-1rtt-handshake title="Example 1-RTT Handshake"} @@ -1283,14 +1283,14 @@ Initial[0]: CRYPTO[CH] 0-RTT[0]: STREAM[0, "..."] -> Initial[0]: CRYPTO[SH] ACK[0] - Handshake[0] CRYPTO[EE, CERT, CV, FIN] + Handshake[0]: KEYS_READY, CRYPTO[EE, CERT, CV, FIN] <- 1-RTT[0]: STREAM[1, "..."] ACK[0] Initial[1]: ACK[0] -Handshake[0]: CRYPTO[FIN], ACK[0] -1-RTT[2]: STREAM[0, "..."] ACK[0] -> +Handshake[0]: KEYS_READY, CRYPTO[FIN], ACK[0] +1-RTT[2]: KEYS_READY, STREAM[0, "..."] ACK[0] -> - 1-RTT[1]: STREAM[55, "..."], ACK[1,2] + 1-RTT[1]: KEYS_READY, STREAM[55, "..."], ACK[1,2] <- Handshake[1]: ACK[0] ~~~~ {: #tls-0rtt-handshake title="Example 0-RTT Handshake"} From 940bac4f4e98893a6da6a671a12a49374fd3c681 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Wed, 13 Feb 2019 13:57:39 +1100 Subject: [PATCH 11/18] Rename frame; optimize some more; clarity; tweak --- draft-ietf-quic-tls.md | 45 +++++++++++----------- draft-ietf-quic-transport.md | 74 +++++++++++++++++------------------- 2 files changed, 58 insertions(+), 61 deletions(-) diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index 445772c761..727b50b9cc 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -1101,7 +1101,7 @@ anticipation of receiving a ClientHello. # Key Update {#key-update} Once the 1-RTT keys are established and confirmed through the use of the -KEYS_READY frame, it is possible to update the keys used to protect packets. +KEYS_ACTIVE frame, it is possible to update the keys used to protect packets. The Key Phase bit is used to indicate which packet protection keys are used to protect the packet. The Key Phase bit is initially set to 0 for the first set @@ -1124,20 +1124,20 @@ and @N. Values in brackets \[] indicate the value of Key Phase bit. Initiating Peer Responding Peer @M [0] QUIC Packets - KEYS_READY + KEYS_ACTIVE --------> QUIC Packets [0] @M - KEYS_READY + KEYS_ACTIVE <-------- ... Update to @N @N [1] QUIC Packets --------> Update to @N ... QUIC Packets [1] @N - KEYS_READY + KEYS_ACTIVE <-------- @N [1] QUIC Packets - KEYS_READY + KEYS_ACTIVE ... Key Update Permitted --------> Key Update Permitted ... @@ -1158,23 +1158,23 @@ corresponding key and IV are created from that secret as defined in The endpoint toggles the value of the Key Phase bit, and uses the updated key and IV to protect all subsequent packets. -An endpoint MUST NOT initiate a key update prior to having received a KEYS_READY -frame in a packet from the current key phase. A subsequent key update can only -be performed after the endpoint has successfully processed a KEYS_READY frame -from a packet with a matching key phase. This ensures that keys are available -to both peers before another can be initiated. +An endpoint MUST NOT initiate a key update prior to having received a +KEYS_ACTIVE frame in a packet from the current key phase. A subsequent key +update can only be performed after the endpoint has successfully processed a +KEYS_ACTIVE frame from a packet with a matching key phase. This ensures that +keys are available to both peers before another can be initiated. Once an endpoint has successfully processed a packet with the same key phase, it -can send a KEYS_READY frame. Endpoints MAY defer sending a KEYS_READY frame +can send a KEYS_ACTIVE frame. Endpoints MAY defer sending a KEYS_ACTIVE frame after a key update (see {{key-update-old-keys}}). ## Responding to a Key Update -An endpoint that sends a KEYS_READY frame can accept further key updates. A key -update can happen even without seeing a KEYS_READY frame from the peer. If a -packet is received with a key phase that differs from the value the endpoint -used to protect the packet containing its last KEYS_READY frame, the endpoint +An endpoint that sends a KEYS_ACTIVE frame can accept further key updates. A +key update can happen even without seeing a KEYS_ACTIVE frame from the peer. If +a packet is received with a key phase that differs from the value the endpoint +used to protect the packet containing its last KEYS_ACTIVE frame, the endpoint creates a new packet protection secret for reading and the corresponding key and IV. An endpoint uses the same key derivation process as its peer uses to generate keys for receiving. @@ -1182,15 +1182,16 @@ generate keys for receiving. If the packet protection is successfully removed using the updated key and IV, then the keys the endpoint initiates a key update in response, as described in {{key-update-initiate}}. An endpoint that responds to a key update MUST send a -KEYS_READY frame to indicate that it is both sending and receiving with updated +KEYS_ACTIVE frame to indicate that it is both sending and receiving with updated keys, though it MAY defer sending the frame (see {{key-update-old-keys}}). An endpoint does not always need to send packets when it detects that its peer has updated keys. The next packet that it sends use the new keys and include -the KEYS_READY frame. If an endpoint detects a second update before it has sent -any packets with updated keys or a KEYS_READY frame, it indicates that its peer -has updated keys twice without awaiting a reciprocal update. An endpoint MUST -treat consecutive key updates as a connection error of type KEY_UPDATE_ERROR. +the KEYS_ACTIVE frame. If an endpoint detects a second update before it has +sent any packets with updated keys or a KEYS_ACTIVE frame, it indicates that its +peer has updated keys twice without awaiting a reciprocal update. An endpoint +MUST treat consecutive key updates as a connection error of type +KEY_UPDATE_ERROR. Endpoints responding to an apparent key update MUST NOT generate a timing side-channel signal that might indicate that the Key Phase bit was invalid (see @@ -1204,12 +1205,12 @@ During a key update, packets protected with older keys might arrive if they were delayed by the network. If those old keys are available, then they can be used to remove packet protection. -After a key update, an endpoint MAY delay sending the KEYS_READY frame by up to +After a key update, an endpoint MAY delay sending the KEYS_ACTIVE frame by up to three times the Probe Timeout (PTO, see {{QUIC-RECOVERY}}) to minimize the number of active keys it maintains. During this time, an endpoint can use old keys to process delayed packets rather than enabling a new key update. This only applies to key updates that use the Key Phase bit; endpoints MUST NOT defer -sending of KEYS_READY during and immediately after the handshake. +sending of KEYS_ACTIVE during and immediately after the handshake. Even if old keys are available, those keys MUST NOT be used to protect packets with packets that have higher packet numbers than packets that were protected diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index 6715cfc164..d5b043b6c3 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -1259,15 +1259,13 @@ Client Server Initial[0]: CRYPTO[CH] -> Initial[0]: CRYPTO[SH] ACK[0] - Handshake[0]: KEYS_READY, CRYPTO[EE, CERT, CV, FIN] + Handshake[0]: KEYS_ACTIVE, CRYPTO[EE, CERT, CV, FIN] <- 1-RTT[0]: STREAM[1, "..."] -Initial[1]: ACK[0] -Handshake[0]: KEYS_READY, CRYPTO[FIN], ACK[0] -1-RTT[0]: KEYS_READY, STREAM[0, "..."], ACK[0] -> +Handshake[0]: KEYS_ACTIVE, CRYPTO[FIN], ACK[0] +1-RTT[0]: KEYS_ACTIVE, STREAM[0, "..."], ACK[0] -> - 1-RTT[1]: KEYS_READY, STREAM[55, "..."], ACK[0] - <- Handshake[1]: ACK[0] + 1-RTT[1]: KEYS_ACTIVE, STREAM[55, "..."], ACK[0] ~~~~ {: #tls-1rtt-handshake title="Example 1-RTT Handshake"} @@ -1283,15 +1281,13 @@ Initial[0]: CRYPTO[CH] 0-RTT[0]: STREAM[0, "..."] -> Initial[0]: CRYPTO[SH] ACK[0] - Handshake[0]: KEYS_READY, CRYPTO[EE, CERT, CV, FIN] + Handshake[0]: KEYS_ACTIVE, CRYPTO[EE, CERT, CV, FIN] <- 1-RTT[0]: STREAM[1, "..."] ACK[0] -Initial[1]: ACK[0] -Handshake[0]: KEYS_READY, CRYPTO[FIN], ACK[0] -1-RTT[2]: KEYS_READY, STREAM[0, "..."] ACK[0] -> +Handshake[0]: KEYS_ACTIVE, CRYPTO[FIN], ACK[0] +1-RTT[2]: KEYS_ACTIVE, STREAM[0, "..."] ACK[0] -> - 1-RTT[1]: KEYS_READY, STREAM[55, "..."], ACK[1,2] - <- Handshake[1]: ACK[0] + 1-RTT[1]: KEYS_ACTIVE, STREAM[55, "..."], ACK[1,2] ~~~~ {: #tls-0rtt-handshake title="Example 0-RTT Handshake"} @@ -2720,7 +2716,7 @@ frames are explained in more detail in {{frame-formats}}. | 0x1a | PATH_CHALLENGE | {{frame-path-challenge}} | | 0x1b | PATH_RESPONSE | {{frame-path-response}} | | 0x1c - 0x1d | CONNECTION_CLOSE | {{frame-connection-close}} | -| 0x1e | KEYS_READY | {{frame-keys-ready}} | +| 0x1e | KEYS_ACTIVE | {{frame-keys-active}} | {: #frame-types title="Frame Types"} All QUIC frames are idempotent in this version of QUIC. That is, a valid @@ -2935,8 +2931,8 @@ containing that information is acknowledged. * PING and PADDING frames contain no information, so lost PING or PADDING frames do not require repair. -* KEYS_READY frames are sent until acknowledged or until newer keys are used for - sending packets. +* KEYS_ACTIVE frames are sent until acknowledged or until newer keys are used + for sending packets. Endpoints SHOULD prioritize retransmission of data over sending new data, unless priorities specified by the application indicate otherwise (see @@ -3605,12 +3601,12 @@ subsequent to the first do not need to fit within a single UDP datagram. #### Abandoning Initial Packets {#discard-initial} -Endpoints cease both sending and processing Initial packets when it receives a -Handshake packet containing a KEYS_READY frame. Though packets might still be -in flight or awaiting acknowledgment, no further Initial packets need to be -exchanged beyond this point. Initial packet protection keys are discarded (see -Section 4.10 of {{QUIC-TLS}}) along with any loss recovery and congestion -control state (see Sections 5.3.1.2 and 6.9 of {{QUIC-RECOVERY}}). +Endpoints cease both sending and processing Initial packets when it both sends +and receives a Handshake packet containing a KEYS_ACTIVE frame. Though packets +might still be in flight or awaiting acknowledgment, no further Initial packets +need to be exchanged beyond this point. Initial packet protection keys are +discarded (see Section 4.10 of {{QUIC-TLS}}) along with any loss recovery and +congestion control state (see Sections 5.3.1.2 and 6.9 of {{QUIC-RECOVERY}}). Any data in CRYPTO frames is discarded - and no longer retransmitted - when Initial keys are discarded. @@ -3725,8 +3721,8 @@ MUST treat receipt of Handshake packets with other frames as a connection error. Like Initial packets (see {{discard-initial}}), data in CRYPTO frames at the Handshake encryption level and the corresponding keys are discarded - and data -is no longer retransmitted - when a KEYS_READY frame is received in a 1-RTT -packet. +is no longer retransmitted - when a KEYS_ACTIVE frame is both sent and received +in a 1-RTT packet. ### Retry Packet {#packet-retry} @@ -5020,41 +5016,41 @@ Reason Phrase: This SHOULD be a UTF-8 encoded string {{!RFC3629}}. -## KEYS_READY Frame {#frame-keys-ready} +## KEYS_ACTIVE Frame {#frame-keys-active} -An endpoint sends a KEYS_READY frame (type=0x1e) to signal that it has installed -keys for reading and writing packets. Receipt of this frame in a packet -indicates that all earlier keys can be safely discarded. +An endpoint sends a KEYS_ACTIVE frame (type=0x1e) to signal that it has +installed keys for both sending and receiving packets. Once this frame has been +both sent and received, older keys can be safely discarded. -The KEYS_READY frame contains no additional fields. +The KEYS_ACTIVE frame contains no additional fields. -The packet that carries a KEYS_READY frame determines which keys are ready. The -keys with the same key phase as those used in the packet that carries the -KEYS_READY frame are present. +The packet that carries a KEYS_ACTIVE frame determines which keys are ready. +The keys with the same key phase as those used in the packet that carries the +KEYS_ACTIVE frame are present. -An endpoint MUST send a KEYS_READY packet in the first packet it sends using +An endpoint MUST send a KEYS_ACTIVE packet in the first packet it sends using keys, but only after having successfully processed a packet using the corresponding keys. -KEYS_READY frames are retransmitted when declared lost, however implementations -need to take care not to retransmit lost KEYS_READY frames if they initiate a +KEYS_ACTIVE frames are retransmitted when declared lost, however implementations +need to take care not to retransmit lost KEYS_ACTIVE frames if they initiate a subsequent key update. This can happen if an acknowledgment for a packet -containing a KEYS_READY frame is lost. +containing a KEYS_ACTIVE frame is lost. -Endpoints MUST NOT send KEYS_READY frames in Initial or 0-RTT packets. +Endpoints MUST NOT send KEYS_ACTIVE frames in Initial or 0-RTT packets. -A KEYS_READY frame used during the handshake can be used to indicate the +A KEYS_ACTIVE frame used during the handshake can be used to indicate the availability of Handshake keys by including it in a Handshake packet. An endpoint sends this frame in its first Handshake packet. Once received, an endpoint can discard Initial keys. -A KEYS_READY frame used after the completion of the handshake in 1-RTT packets +A KEYS_ACTIVE frame used after the completion of the handshake in 1-RTT packets indicates that Handshake keys are no longer needed. A client sends this frame in its first 1-RTT packet, and a server sends this frame in the first packet it sends after completing the handshake. Note that a server might send 1-RTT keys prior to this. -An endpoint uses the KEYS_READY frame in 1-RTT packets to indicate that it is +An endpoint uses the KEYS_ACTIVE frame in 1-RTT packets to indicate that it is able to receive a key update (see Section 6 of {{QUIC-TLS}}). From 3fca7a585564c7dd939170d51c714d8b34d7f3bf Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Wed, 13 Feb 2019 15:27:26 +1000 Subject: [PATCH 12/18] 1-RTT KEYS_ACTIVE can be used to discard Initial --- draft-ietf-quic-transport.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index d5b043b6c3..23e07ec6b1 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -3602,10 +3602,10 @@ subsequent to the first do not need to fit within a single UDP datagram. #### Abandoning Initial Packets {#discard-initial} Endpoints cease both sending and processing Initial packets when it both sends -and receives a Handshake packet containing a KEYS_ACTIVE frame. Though packets -might still be in flight or awaiting acknowledgment, no further Initial packets -need to be exchanged beyond this point. Initial packet protection keys are -discarded (see Section 4.10 of {{QUIC-TLS}}) along with any loss recovery and +and receives a Handshake or 1-RTT packet containing a KEYS_ACTIVE frame. Though +packets might still be in flight or awaiting acknowledgment, no further Initial +packets need to be exchanged beyond this point. Initial packet protection keys +are discarded (see Section 4.10 of {{QUIC-TLS}}) along with any loss recovery and congestion control state (see Sections 5.3.1.2 and 6.9 of {{QUIC-RECOVERY}}). Any data in CRYPTO frames is discarded - and no longer retransmitted - when From 8fd93b85d830c8be4cf3f183a804345d4fff0180 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Wed, 13 Feb 2019 15:31:42 +1000 Subject: [PATCH 13/18] I should not edit on my phone --- draft-ietf-quic-transport.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index 23e07ec6b1..e887e89ab0 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -3605,8 +3605,8 @@ Endpoints cease both sending and processing Initial packets when it both sends and receives a Handshake or 1-RTT packet containing a KEYS_ACTIVE frame. Though packets might still be in flight or awaiting acknowledgment, no further Initial packets need to be exchanged beyond this point. Initial packet protection keys -are discarded (see Section 4.10 of {{QUIC-TLS}}) along with any loss recovery and -congestion control state (see Sections 5.3.1.2 and 6.9 of {{QUIC-RECOVERY}}). +are discarded (see Section 4.10 of {{QUIC-TLS}}) along with any loss recovery +and congestion control state (see Sections 5.3.1.2 and 6.9 of {{QUIC-RECOVERY}}). Any data in CRYPTO frames is discarded - and no longer retransmitted - when Initial keys are discarded. From efeaf0dadda0471d9446f436458a680aaf6375d9 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Thu, 14 Feb 2019 07:41:10 +1100 Subject: [PATCH 14/18] reflow2 --- draft-ietf-quic-transport.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index e887e89ab0..933274d2ad 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -3606,7 +3606,8 @@ and receives a Handshake or 1-RTT packet containing a KEYS_ACTIVE frame. Though packets might still be in flight or awaiting acknowledgment, no further Initial packets need to be exchanged beyond this point. Initial packet protection keys are discarded (see Section 4.10 of {{QUIC-TLS}}) along with any loss recovery -and congestion control state (see Sections 5.3.1.2 and 6.9 of {{QUIC-RECOVERY}}). +and congestion control state (see Sections 5.3.1.2 and 6.9 of +{{QUIC-RECOVERY}}). Any data in CRYPTO frames is discarded - and no longer retransmitted - when Initial keys are discarded. From 5fb15c8a413ee38ccf1a8ee86f327fbcac1f2c86 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Thu, 14 Feb 2019 12:00:53 +1100 Subject: [PATCH 15/18] Fix some words --- draft-ietf-quic-tls.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index 727b50b9cc..f831dd6298 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -863,7 +863,7 @@ 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 Update +this covers the reserved bits and the Packet Number Length field; the Key Phase bit is also protected for packets with a short header. The same header protection key is used for the duration of the connection, with @@ -1158,11 +1158,12 @@ corresponding key and IV are created from that secret as defined in The endpoint toggles the value of the Key Phase bit, and uses the updated key and IV to protect all subsequent packets. -An endpoint MUST NOT initiate a key update prior to having received a -KEYS_ACTIVE frame in a packet from the current key phase. A subsequent key -update can only be performed after the endpoint has successfully processed a -KEYS_ACTIVE frame from a packet with a matching key phase. This ensures that -keys are available to both peers before another can be initiated. +An endpoint MUST NOT initiate a key update prior to having received and +processed a KEYS_ACTIVE frame in a packet from the current key phase. A +subsequent key update can only be performed after the endpoint has successfully +received and processed a KEYS_ACTIVE frame from a packet with a matching key +phase. This ensures that keys are available to both peers before another can be +initiated. Once an endpoint has successfully processed a packet with the same key phase, it can send a KEYS_ACTIVE frame. Endpoints MAY defer sending a KEYS_ACTIVE frame From b3d8ff1a8c9a9bd280c4ed7ea8501af7ebfb79d5 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Thu, 14 Feb 2019 12:30:32 +1100 Subject: [PATCH 16/18] Varied feedback --- draft-ietf-quic-tls.md | 38 ++++++++++++++++++++++++------------ draft-ietf-quic-transport.md | 15 +++++++------- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index f831dd6298..3522ef77f8 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -1159,15 +1159,22 @@ The endpoint toggles the value of the Key Phase bit, and uses the updated key and IV to protect all subsequent packets. An endpoint MUST NOT initiate a key update prior to having received and -processed a KEYS_ACTIVE frame in a packet from the current key phase. A -subsequent key update can only be performed after the endpoint has successfully -received and processed a KEYS_ACTIVE frame from a packet with a matching key -phase. This ensures that keys are available to both peers before another can be -initiated. +successfully processed a KEYS_ACTIVE frame contained in a packet from the +current key phase. This ensures that keys are available to both peers before +another can be initiated. + +Note: + +: Changes in keys from Initial to Handshake and from Handshake to 1-RTT don't + use this key update process. Key changes during the handshake do not need to + wait for a KEYS_ACTIVE frame, they are driven solely by changes in the TLS + handshake. The KEYS_ACTIVE frame is used to allow Initial and Handshake keys + to be discarded when they are no longer needed and - in the case of the first + 1-RTT key phase - to enable the first key update. Once an endpoint has successfully processed a packet with the same key phase, it -can send a KEYS_ACTIVE frame. Endpoints MAY defer sending a KEYS_ACTIVE frame -after a key update (see {{key-update-old-keys}}). +MUST send a KEYS_ACTIVE frame, though endpoints MAY defer sending the frame (see +{{key-update-old-keys}}). ## Responding to a Key Update @@ -1180,8 +1187,8 @@ creates a new packet protection secret for reading and the corresponding key and IV. An endpoint uses the same key derivation process as its peer uses to generate keys for receiving. -If the packet protection is successfully removed using the updated key and IV, -then the keys the endpoint initiates a key update in response, as described in +If the packet is successfully processed using the updated key and IV, then the +keys the endpoint initiates a key update in response, as described in {{key-update-initiate}}. An endpoint that responds to a key update MUST send a KEYS_ACTIVE frame to indicate that it is both sending and receiving with updated keys, though it MAY defer sending the frame (see {{key-update-old-keys}}). @@ -1197,7 +1204,10 @@ KEY_UPDATE_ERROR. Endpoints responding to an apparent key update MUST NOT generate a timing side-channel signal that might indicate that the Key Phase bit was invalid (see {{header-protect-analysis}}). Endpoints can use dummy packet protection keys in -place of discarded keys when key updates are not permitted. +place of discarded keys when key updates are not permitted; using dummy keys +will generate no variation in the timing signal produced by attempting to remove +packet protection, but all packets with an invalid Key Phase bit will be +rejected. ## Using Old Keys {#key-update-old-keys} @@ -1206,12 +1216,16 @@ During a key update, packets protected with older keys might arrive if they were delayed by the network. If those old keys are available, then they can be used to remove packet protection. +An endpoint always sends packets that are protected with the newest keys. Keys +used for protecting packets that an endpoint sends can be discarded immediately +after newer keys are available. + After a key update, an endpoint MAY delay sending the KEYS_ACTIVE frame by up to three times the Probe Timeout (PTO, see {{QUIC-RECOVERY}}) to minimize the number of active keys it maintains. During this time, an endpoint can use old keys to process delayed packets rather than enabling a new key update. This -only applies to key updates that use the Key Phase bit; endpoints MUST NOT defer -sending of KEYS_ACTIVE during and immediately after the handshake. +only applies to key updates; endpoints MUST NOT defer sending of KEYS_ACTIVE +during and immediately after the handshake. Even if old keys are available, those keys MUST NOT be used to protect packets with packets that have higher packet numbers than packets that were protected diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index 933274d2ad..234d89df4a 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -5025,13 +5025,13 @@ both sent and received, older keys can be safely discarded. The KEYS_ACTIVE frame contains no additional fields. -The packet that carries a KEYS_ACTIVE frame determines which keys are ready. -The keys with the same key phase as those used in the packet that carries the -KEYS_ACTIVE frame are present. +The packet that carries a KEYS_ACTIVE frame determines which keys are active and +usable. The keys with the same key phase as those used in the packet that +carries the KEYS_ACTIVE frame are active. An endpoint MUST send a KEYS_ACTIVE packet in the first packet it sends using -keys, but only after having successfully processed a packet using the -corresponding keys. +keys, but only if it is also able to receive packets that are protected using +the corresponding keys. KEYS_ACTIVE frames are retransmitted when declared lost, however implementations need to take care not to retransmit lost KEYS_ACTIVE frames if they initiate a @@ -5048,8 +5048,9 @@ endpoint can discard Initial keys. A KEYS_ACTIVE frame used after the completion of the handshake in 1-RTT packets indicates that Handshake keys are no longer needed. A client sends this frame in its first 1-RTT packet, and a server sends this frame in the first packet it -sends after completing the handshake. Note that a server might send 1-RTT keys -prior to this. +sends after completing the handshake. A server might send 1-RTT keys prior to +this; a server MUST NOT use 1-RTT keys for removing packet protection until the +cryptographic handshake is complete. An endpoint uses the KEYS_ACTIVE frame in 1-RTT packets to indicate that it is able to receive a key update (see Section 6 of {{QUIC-TLS}}). From b56d3d968526ed70767ce4a96aa367c4e65496b3 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Thu, 14 Feb 2019 13:06:00 +1100 Subject: [PATCH 17/18] You need to update read keys too --- draft-ietf-quic-tls.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index 3522ef77f8..2f0b7888d0 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -1172,8 +1172,12 @@ Note: to be discarded when they are no longer needed and - in the case of the first 1-RTT key phase - to enable the first key update. -Once an endpoint has successfully processed a packet with the same key phase, it -MUST send a KEYS_ACTIVE frame, though endpoints MAY defer sending the frame (see +The endpoint that initiates a key update also updates the keys that it uses for +receiving packets. These keys will be needed to process packets the peer sends +after updating. An endpoint needs to retain old keys so that packets sent by +the peer prior to receiving the key update can be processed. Once an endpoint +has successfully processed a packet using the new keys, it MUST send a +KEYS_ACTIVE frame, though endpoints MAY defer sending the frame (see {{key-update-old-keys}}). From 5b075a83cfc33611d51fbb417c83e3d84cf047dd Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Thu, 14 Feb 2019 16:25:30 +1100 Subject: [PATCH 18/18] Review feedback --- draft-ietf-quic-tls.md | 35 +++++++++++++++++++---------------- draft-ietf-quic-transport.md | 26 +++++++++++--------------- 2 files changed, 30 insertions(+), 31 deletions(-) diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index 2f0b7888d0..88e13e739c 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -1103,9 +1103,9 @@ anticipation of receiving a ClientHello. Once the 1-RTT keys are established and confirmed through the use of the KEYS_ACTIVE frame, it is possible to update the keys used to protect packets. -The Key Phase bit is used to indicate which packet protection keys are used to -protect the packet. The Key Phase bit is initially set to 0 for the first set -of 1-RTT packets. The Key Phase bit is toggled to signal each key update. +The Key Phase bit indicates which packet protection keys are used to protect the +packet. The Key Phase bit is initially set to 0 for the first set of 1-RTT +packets and toggled to signal each subsequent key update. The Key Phase bit allows a recipient to detect a change in keying material without needing to receive the first packet that triggered the change. An @@ -1155,8 +1155,8 @@ uses the KDF function provided by TLS with a label of "quic ku". The corresponding key and IV are created from that secret as defined in {{protection-keys}}. The header protection key is not updated. -The endpoint toggles the value of the Key Phase bit, and uses the updated key -and IV to protect all subsequent packets. +The endpoint toggles the value of the Key Phase bit and uses the updated key and +IV to protect all subsequent packets. An endpoint MUST NOT initiate a key update prior to having received and successfully processed a KEYS_ACTIVE frame contained in a packet from the @@ -1186,10 +1186,10 @@ KEYS_ACTIVE frame, though endpoints MAY defer sending the frame (see An endpoint that sends a KEYS_ACTIVE frame can accept further key updates. A key update can happen even without seeing a KEYS_ACTIVE frame from the peer. If a packet is received with a key phase that differs from the value the endpoint -used to protect the packet containing its last KEYS_ACTIVE frame, the endpoint -creates a new packet protection secret for reading and the corresponding key and -IV. An endpoint uses the same key derivation process as its peer uses to -generate keys for receiving. +used to protect the last packet it sent, the endpoint creates a new packet +protection secret for reading and the corresponding key and IV. An endpoint +uses the same key derivation process as its peer uses to generate keys for +receiving. If the packet is successfully processed using the updated key and IV, then the keys the endpoint initiates a key update in response, as described in @@ -1213,6 +1213,9 @@ will generate no variation in the timing signal produced by attempting to remove packet protection, but all packets with an invalid Key Phase bit will be rejected. +An endpoint might not receive an acknowledgment for the packet that contains a +KEYS_ACTIVE before receiving another key update. + ## Using Old Keys {#key-update-old-keys} @@ -1232,18 +1235,18 @@ only applies to key updates; endpoints MUST NOT defer sending of KEYS_ACTIVE during and immediately after the handshake. Even if old keys are available, those keys MUST NOT be used to protect packets -with packets that have higher packet numbers than packets that were protected -with newer keys. An endpoint that successfully removes protection with old keys -when newer keys were used for packets with lower packet numbers MUST treat this -as a connection error of type KEY_UPDATE_ERROR. +that have higher packet numbers than packets that were protected with newer +keys. An endpoint that successfully removes protection with old keys when newer +keys were used for packets with lower packet numbers MUST treat this as a +connection error of type KEY_UPDATE_ERROR. An endpoint SHOULD retain old read keys for a period of no more than three times the current PTO. After this period, old read keys and their corresponding secrets SHOULD be discarded. -An endpoint that receives a packet protected with old keys that includes an -acknowledgement for a packet protected with newer keys MAY treat that as a -connection error of type KEY_UPDATE_ERROR. +An endpoint that receives an acknowledgement for a packet protected with new +keys in a packet protected with older keys MAY treat that as a connection error +of type KEY_UPDATE_ERROR. ## Key Update Frequency diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index 234d89df4a..6d60b199cb 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -3414,7 +3414,7 @@ packet type. While type-specific semantics for this version are described in the following sections, several long-header packets in this version of QUIC contain these additional fields: -Reserved Bit (R): +Reserved Bits (R): : Two bits (those with a mask of 0x0c) of byte 0 are reserved across multiple packet types. These bits are protected using header protection (see Section @@ -5029,10 +5029,6 @@ The packet that carries a KEYS_ACTIVE frame determines which keys are active and usable. The keys with the same key phase as those used in the packet that carries the KEYS_ACTIVE frame are active. -An endpoint MUST send a KEYS_ACTIVE packet in the first packet it sends using -keys, but only if it is also able to receive packets that are protected using -the corresponding keys. - KEYS_ACTIVE frames are retransmitted when declared lost, however implementations need to take care not to retransmit lost KEYS_ACTIVE frames if they initiate a subsequent key update. This can happen if an acknowledgment for a packet @@ -5040,17 +5036,17 @@ containing a KEYS_ACTIVE frame is lost. Endpoints MUST NOT send KEYS_ACTIVE frames in Initial or 0-RTT packets. -A KEYS_ACTIVE frame used during the handshake can be used to indicate the +A KEYS_ACTIVE frame sent during the handshake can be used to indicate the availability of Handshake keys by including it in a Handshake packet. An -endpoint sends this frame in its first Handshake packet. Once received, an -endpoint can discard Initial keys. - -A KEYS_ACTIVE frame used after the completion of the handshake in 1-RTT packets -indicates that Handshake keys are no longer needed. A client sends this frame -in its first 1-RTT packet, and a server sends this frame in the first packet it -sends after completing the handshake. A server might send 1-RTT keys prior to -this; a server MUST NOT use 1-RTT keys for removing packet protection until the -cryptographic handshake is complete. +endpoint MUST send this frame in its first Handshake packet. Once received, an +endpoint can discard Initial keys. An endpoint SHOULD send a KEYS_ACTIVE frame +in every Handshake packet it sends. + +A KEYS_ACTIVE frame sent in 1-RTT packets indicates that Handshake keys are no +longer needed. A client MUST send this frame in its first 1-RTT packet, and a +server MUST send this frame in the first packet it sends after completing the +handshake. A server might send 1-RTT packets prior to this; a server MUST NOT +process 1-RTT packets until the cryptographic handshake is complete. An endpoint uses the KEYS_ACTIVE frame in 1-RTT packets to indicate that it is able to receive a key update (see Section 6 of {{QUIC-TLS}}).