Draft: draft-ietf-quic-tls

Commentary: This makes some significant editorial changes to the key update section , hopefully making the various activities clearer and more explicit . In the process , I am also trying to address , which is the timing sidechannel created by having the generation of updated keys inline with packet processing . In doing so , I 'm suggesting that endpoints create the next keys at some time after the key update happens . Right now , I 'm thinking 1 - 2 PTOs is probably close enough to workable . I 've limited this at 3PTO . This is , however , just a ( firm ) suggestion at this stage . For endpoints that only want to keep 2 sets of keys , this is probably the right time frame , especially if we keep the current advice for  before a subsequent update . The effect of this is that attempts to update at certain times could cause all packets after the update to be discarded . That would only happen if implementations consistently ignored advice on update frequency , so I think that 's tolerable , but I 'd like input on this . ( This also attempts to take up the advice from the other , older PRs on this subject . ) 
 Thanks Do you have any opinion on the advice about how many keys to hold , when to flip from keeping previous vs. next ( especially if you are doing just two keys ) and the technical changes ? 
 It seemed to me that the advice on how to use 2 keys seemed correct and appropriate . It 's a bit unfortunate that the advice is scattered , but I assume that 's because we have to talk about the features rather than talking about implementation strategies . I also like the introduction of  . 
 Though consensus has been declared , I talked to about reviewing this and I will wait for that review before merging . 
 While I 'm fully supportive of the spirit of this PR , I still have some comments on here that have n't been addressed ( for example the implementation guidance text was apparently accidentally removed ) 
 My bad I had restored that text in my local copy , but failed to push . 
 We 've been back and forth on this issue for a while now and I honestly do n't know what the answer is . picks a value that we have n't seen before , or we could - as I think some have assumed - use the TLS value of " traffic upd " . I think that because QUIC is managing this , it should be a quic - specific label . See also and . 
 I would not strongly suggest this , but I wonder if it be possible to define the derivation function inside QUIC too . If the labels are going to be different , it would be helpful to the readers to have all the definition in one place . 
 +1 to clarifying what the label is . I do n't have a strong opinion on what the label should be as long as it 's in the quic - tls draft . 
 I also agree the label should be explicitly defined in the quic - tls spec . I do like  's suggestion as well , to completely define the derivation function . I do n't care too much what the label is . We were using ( and interop'ing with it ) . 
 There 's a difference between defining the function and providing a much clearer example of what the function is for TLS 1.3 . I 've chosen the latter on the basis that the cryptographic handshake function provides us with a KDF and that we should n't be making our own if we can avoid it . If TLS 1.4 wants to use a different KDF , then that will be used here instead . 
 Discussed in Cupertino . has proposal . 
 When receiving a packet with an unexpected key phase , an implementation should compute the new keys : This creates a timing side - channel , since an attacker can modify the KEYPHASE bit , thereby making a peer compute the next key generation . The packet will be discarded , since the header is protected by the AEAD , but the fact that the key is computed on receipt of that packet is a side - channel that might be used to recover the header protection key . The way to avoid this side - channel is to pre - compute the N+1 key when rolling over keys from key phase N-1 to N. An implementation would then use the N+1 keys when receiving a packet with an unexpected KEY_PHASE , in exactly the same way it would do decryption on a packet sent at key phase N. This however contradicts the text that claims that an implementation may choose to only keep two read keys at any given moment : Directly after a key update , an implementation would have to store ( at least ) 3 key generations : N-1 for a duration of 3 PTO , in order to be able to decrypt delayed / reordered packets , N , as well as the precomputed N+1 to avoid the timing side - channel described above . I do n't think that storing 3 keys is a problem ( I think disagrees , I 'll let him explain his reasoning himself ) , but the spec should n't pretend that it 's possible to create an implementation that both is n't vulnerable to the timing side - channel and at the same time gracefully handles moderate amounts of reordering around a key update . 
 I think you are correct in pointing out that there is a timing side - channel , and that we need to fix the issue . OTOH , I disagree that requiring all endpoints to be capable of retaining 3 keys is not a good way of fixing the issue due to the following reasons . Firstly , I do not think we can justify why an endpoint needs to be capable of retaining that much keys , even though Key Update is expected to happen very rarely . The purpose of Key Update is to replace a key after extensive use , we would never be using a key that becomes weak just after couple of PTOs . Considering that , using 2 keys should be sufficient ; 3 keys is likely a sign of a needlessly complex design . Let 's compare the proposal of the 3 - key design with a 2 - key design ( that allows the receiver to delay the installation of the next key for 3 PTO after since Key Update , which is ) . In the 3 - key design , the next key is installed when a Key Update happens . The old key is disposed 3 PTO after a Key Update , and the slot becomes NULL . Note also that an endpoint needs to retain a mapping between packet number and key phase to determine whether an incoming packet is to be decrypted using the oldest key or the newest key ( those two key share the same KEY_PHASE bit on the wire ) . In the 2 - key design , installation of the next key and the disposal of the old key happens at the same moment ( i.e. 3 PTO after a Key Update ) . An endpoint would always retain 2 keys once the handshake is confirmed . There is no need for retaining a mapping between packet numbers and key phases . The oddity of the key phase bit directly maps to the decryption key . To me it seems that the latter is simpler . As stated above , there is no need for doing Key Update every 3 PTO , and therefore , assuming that we need to make a change due to the attack vector , I think we should simply allow endpoints delay the installation of the next key rather than changing the increasing the minimum state that an endpoint needs to be capable of maintaining . 
 I agree , there 's not really a need to do key updates that frequently . However , I like the fact that we 're currently defining a clear rule : An endpoint is allowed to update to N+1 as soon as it has received an acknowledgement for a packet sent at key phase N. You should still keep track of the packet number at which the key update happened , in order to check that the peer is not reusing the old key to encrypt packets after it already switched to new keys . Strictly speaking , this is not required for a working implementation , but it 's a really easy check to catch a misbehaving peer ( or detect an active attack ) . As I 've mentioned in the discussion in , the reason I 'm skeptical about delaying key updates by 3 PTO ( and effectively dropping all packets with a higher key phase until this period is over ) is that we 're replacing a very clear definition by an approximate rule : the PTO is calculated locally , and depending on the network conditions , the two endpoints might have different opinions about the exact value of the PTO . An endpoint that wants to ensure that no packets are dropped due to the unavailability of keys would have no choice but to wait 3 PTO . While this should be well within the safety limits of the cipher suites we 're using , not having a clear criterion seems to be a sign of suboptimal protocol design . 
 Perhaps we should state that an endpoint should precompute the key early but not update keys too frequently to prevent timing attacks and overhead . That is not necessarily a bad thing , but it is unfortunate that there is no clear definition . We could also say the idle timeout period . As long as we compute keys using  it might not be a concern , but computing keys too frequently could exhaust safety parameters on other potentially faster algorithms . 
 To clarify , the key phase bit is inside header protection , so the attacker in question is the peer ? 
 No , this is an on - path attack . Header protection is not authenticated , so an attacker can just flip bits in the header . Decrypting the packet will fail then , since the header is part of the authenticated data used in the AEAD . We have a timing side - channel as soon as we treat packets differently based on values in the unprotected header , before authenticating the packet . This is analogous to the . 
 Thanks for the extra explanation , I 'm not sure that 's a very good side - channel , but I agree it is one . 
 Does anyone have any ideas what kind of actual attack could take advantage of this ? The attacker can only cause you to install your keys early once per key phase change . Assuming you hardly every change key phase , what then ? I agree it 's a way the unauthenticated attacker can change your state , but I do n't think it 's a big enough problem we need to worry about fixing . 
 That 's a good question . I agree that this attack vector does n't look very promising at first sight , but then again I 'm always surprised what cryptanalysts can extract from a single bit . That depends . If you create the new keys , try decrypt the packet , and then discard the keys ( if decryption fails ) , the attacker has an unbounded number of tries . Obviously , this would also be a DoS vector , since computing new keys is more than order of magnitude more expensive than an AEAD operation ( at least in my implementation ) . If you cache the new keys once they are computed , then the attacker indeed only has a single shot per key phase . However , then you might as precompute the new keys when installing the current key phase . The problem with that is that the spec currently suggests that you only ever need to keep state for 2 key generations at any given moment . This is incompatible with caching the keys for the next key phase , as I described above . 
 But the current spec . also recommends to wait for 3 PTO before initiating the next Key Update . That would not change , and as we agree , nothing in practice requires us to do Key Updates every 3 PTO . In the 2 - key design , installation of the next key and the disposal of the old key happens at the same moment ( i.e. 3 PTO after a Key Update ) . An endpoint would always retain 2 keys once the handshake is confirmed . There is no need for retaining a mapping between packet numbers and key phases . The oddity of the key phase bit directly maps to the decryption key . I agree that an endpoint might still want to track the packet number at which key update happened . But even in such case , the simplicity of the 2 - key design still exists , in sense that you 'd only use it for detecting a suspicious peer . It 's much straightforward and easier to test , because the rare case ( of actually using 3 keys at the same time ) never happens . To clarify , I am not saying that 3 - key design is incorrect . My argument is that lack of clear signal is a non - issue ( because there is no need to do a Key Update every 3 PTO or more frequently ) , and that therefore that argument can not be used for prohibiting people to choose the 2 - key design ( which is simpler ) . 
 Is n't the middle ground here to pre - compute the N+1 key when the N-1 key is dropped , with the drop happening at the first of : 3xPTO after the N key was first successfully used First arrival of a packet which purports to be N+1 The attacker 's ability at that point would be to cause any delayed N-1 packets to be dropped , but if we 're presuming the ability to bit - flip , they can cause those packets to be invalid and dropped anyway . 
 That certainly reduces the information being potentially exposed to the attacker to one bit per every key update . But no less than that for example when an attacker injects two packets slightly more frequent than every 3 PTO , with the only difference between the two packets being the value of the KEY_PHASE bit . In such an attack scenario , the attacker can tell which of the two packets caused the calculation of the updated key for every key update . Admittedly , the leak is tiny ; but I am not sure if it is tiny enough that we can ignore . 
 To recap my comments at the mic : it 's not clear to me what the attacker is learning here . Can someone expand on this ? 
 Discussed in Montreal : to work with and to work out the details 
 I 'd like to second comment at the mic . I do n’t think this is an issue for which we need text . Without loss of generality , let ’s assume that in the worst case an attacker learns the entire unprotected header bytes for every packet . ( That is , that header protection does nothing overwhelmingly helpful . ) Revisiting the header protection algorithm , it basically works as follows : where H ’ and H are the protected and unprotected header bytes , respectively , and sample is known to the adversary . If we assume mask is the output of a PRP , and therefore both IND - CPA secure and KPA secure , an adversary learns nothing from known plaintext and ciphertext pairs . ( The typical game - based IND - CPA security definition says that an adversary with access to an oracle for encrypting any message Mi of its choice has negligible probability in selecting b , upon giving the challenger M0 and M1 and receiving an encryption of Mb . Recovering the header protection key would break this assumption , as it would let the adversary encrypt M0 and M1 -- without the oracle -- and trivially match against M_b . ) All that said , I think adding text describing that endpoints should precompute keys is fine . After all , it 'd be nice if header protection worked as intended . 
 and to resolve their issue before we 'll take it forward 
 Discussed in Singapore ; proposal is to change SHOULD to MAY regarding pregeneration of next phase of keys . 
 Thanks for adding back the implementation text . I like the new text . I would personally prefer to see all the timing side - channel text in its own subsection , because it makes the more important part of the spec harder to read , and I do n't see this attack as important enough to warrant worrying about when trying to understand key updates . A few nits . I 've asked if he could take another look as well . I'm skeptical of this anti - timing advice and think we should remove it .
Paragraph (version A):
Each upper layer (handshake, alerts, and application data) is carried
as a series of typed TLS records.  Records are individually
cryptographically protected and then transmitted over a reliable
transport (typically TCP) which provides sequencing and guaranteed
delivery.
Paragraph (version A):
The TLS authenticated key exchange occurs between two entities:
client and server.  The client initiates the exchange and the server
responds.  If the key exchange completes successfully, both client
and server will agree on a secret.  TLS supports both pre-shared key
(PSK) and Diffie-Hellman (DH) key exchanges.  PSK is the basis for
0-RTT; the latter provides perfect forward secrecy (PFS) when the DH
keys are destroyed.
Paragraph (version B):
Internally, TLS is a layered protocol, with the structure shown in
tls-layers.
Paragraph (version B):
QUIC QUIC-TRANSPORT assumes responsibility for the confidentiality
and integrity protection of packets.  For this it uses keys derived
from a TLS handshake TLS13, but instead of carrying TLS records over
QUIC (as with TCP), TLS Handshake and Alert messages are carried
directly over the QUIC transport, which takes over the
responsibilities of the TLS record layer, as shown in quic-layers.
Paragraph (version B):
Rather than a strict layering, these two protocols cooperate: QUIC
uses the TLS handshake; TLS uses the reliability, ordered delivery,
and record layer provided by QUIC.
Paragraph (version A):
A server MUST NOT use post-handshake client authentication (see
Section 4.6.2 of TLS13).
Paragraph (version B):
A server MUST NOT use post-handshake client authentication (as
defined in Section 4.6.2 of TLS13), because the multiplexing offered
by QUIC prevents clients from correlating the certificate request
with the application-level event that triggered it (see HTTP2-TLS13).
More specifically, servers MUST NOT send post-handshake TLS
CertificateRequest messages and clients MUST treat receipt of such
messages as a connection error of type PROTOCOL_VIOLATION.
Paragraph (version B):
QUIC requires additional transport state to be associated with a
0-RTT session ticket.  One common way to implement this is using
stateless session tickets and storing this state in the session
ticket.  Application protocols that use QUIC might have similar
requirements regarding associating or storing state.  This associated
state is used for deciding whether early data must be rejected.  For
example, HTTP/3 (QUIC-HTTP) settings determine how early data from
the client is interpreted.  Other applications using QUIC could have
different requirements for determining whether to accept or reject
early data.
Paragraph (version B):
Once the handshake is confirmed (see handshake-confirmed), an
endpoint MAY initiate a key update.
Paragraph (version B):
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.
Paragraph (version B):
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 bit updates
keys and decrypts the packet that contains the changed value.
Paragraph (version A):
This 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.
Paragraph (version A):
A packet that triggers a key update could arrive after the receiving
endpoint successfully processed 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.
Paragraph (version B):
ex-key-update shows a key update process, where the initial set of
keys used (identified with @M) are replaced by updated keys
(identified with @N).  The value of the Key Phase bit is indicated in
brackets [].
Paragraph (version B):
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.
Paragraph (version B):
The endpoint toggles the value of the Key Phase bit and uses the
updated key and IV to protect all subsequent packets.
Paragraph (version B):
Keys of packets other than the 1-RTT packets are never updated;
their keys are derived solely from the TLS handshake state.
Paragraph (version B):
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.
Paragraph (version B):
If a packet is successfully processed using the next key and IV, then
the peer has initiated a key update.  The endpoint MUST update its
send keys to the corresponding key phase in response, as described in
key-update-initiate.  Sending keys MUST be updated before sending an
acknowledgement for the packet that was received with updated keys.
By acknowledging the packet that triggered the key update in a packet
protected with the updated keys, the endpoint signals that the key
update is complete.
Paragraph (version B):
An endpoint can defer sending the packet or acknowledgement according
to its normal packet sending behaviour; it is not necessary to
immediately generate a packet in response to a key update.  The next
packet sent by the endpoint will use the updated keys.  The next
packet that contains an acknowledgement will cause the key update to
be completed.  If an endpoint detects a second update before it has
sent any packets with updated keys containing an acknowledgement for
the packet that initiated the key update, it indicates that its peer
has updated keys twice without awaiting confirmation.  An endpoint
MAY treat consecutive key updates as a connection error of type
KEY_UPDATE_ERROR.
Paragraph (version B):
An endpoint that receives an acknowledgement that is carried in a
packet protected with old keys where any acknowledged packet was
protected with newer keys MAY treat that as a connection error of
type KEY_UPDATE_ERROR.  This indicates that a peer has received and
acknowledged a packet that initiates a key update, but has not
updated keys in response.
Paragraph (version B):
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 yet permitted.  Using dummy keys will generate no variation
in the timing signal produced by attempting to remove packet
protection, and results in all packets with an invalid Key Phase bit
being rejected.
Paragraph (version B):
The process of creating new packet protection keys for receiving
packets could reveal that a key update has occurred.  An endpoint MAY
perform this process as part of packet processing, but this creates a
timing signal that can be used by an attacker to learn when key
updates happen and thus the value of the Key Phase bit in certain
packets.  Endpoints SHOULD instead defer the creation of the next set
of receive packet protection keys until some time after a key update
completes, up to three times the PTO; see old-keys-recv.
Paragraph (version B):
Once generated, the next set of packet protection keys SHOULD be
retained, even if the packet that was received was subsequently
discarded.  Packets containing apparent key updates are easy to forge
and - while the process of key update does not require significant
effort - triggering this process could be used by an attacker for
DoS.
Paragraph (version B):
For this reason, endpoints MUST be able to retain two sets of packet
protection keys for receiving packets: the current and the next.
Retaining the previous keys in addition to these might improve
performance, but this is not essential.
Paragraph (version B):
Packets with higher packet numbers MUST be protected with either the
same or newer packet protection keys than packets with lower packet
numbers.  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.
Paragraph (version B):
For receiving packets during a key update, packets protected with
older keys might arrive if they were delayed by the network.
Retaining old packet protection keys allows these packets to be
successfully processed.
Paragraph (version B):
As packets protected with keys from the next key phase use the same
Key Phase value as those protected with keys from the previous key
phase, it can be necessary to distinguish between the two.  This can
be done using packet numbers.  A recovered packet number that is
lower than any packet number from the current key phase uses the
previous packet protection keys; a recovered packet number that is
higher than any packet number from the current key phase requires the
use of the next packet protection keys.
Paragraph (version B):
Some care is necessary to ensure that any process for selecting
between previous, current, and next packet protection keys does not
expose a timing side channel that might reveal which keys were used
to remove packet protection.  See hp-side-channel for more
information.
Paragraph (version B):
Alternatively, endpoints can retain only two sets of packet
protection keys, swapping previous for next after enough time has
passed to allow for reordering in the network.  In this case, the Key
Phase bit alone can be used to select keys.
Paragraph (version B):
Endpoints need to allow for the possibility that a peer might not be
able to decrypt packets that initiate a key update during the period
when it retains old keys.  Endpoints SHOULD wait three times the PTO
before initiating a key update after receiving an acknowledgment that
confirms that the previous key update was received.  Failing to allow
sufficient time could lead to packets being discarded.
Paragraph (version B):
The KEY_UPDATE_ERROR error code (0xE) is used to signal errors
related to key updates.
Paragraph (version A):
QUIC transport parameters are carried in a TLS extension.  Different
versions of QUIC might define a different format for this struct.
Paragraph (version B):
QUIC transport parameters are carried in a TLS extension.  Different
versions of QUIC might define a different method for negotiating
transport configuration.
Paragraph (version B):
During a key update, the time taken to generate new keys could reveal
through timing side-channels that a key update has occurred.
Alternatively, where an attacker injects packets this side-channel
could reveal the value of the Key Phase on injected packets.  After
receiving a key update, an endpoint SHOULD generate and save the next
set of receive packet protection keys, as described in receive-key-
generation.  By generating new keys before a key update is received,
receipt of packets will not create timing signals that leak the value
of the Key Phase.
Paragraph (version B):
This depends on not doing this key generation during packet
processing and it can require that endpoints maintain three sets of
packet protection keys for receiving: for the previous key phase, for
the current key phase, and for the next key phase.  Endpoints can
instead choose to defer generation of the next receive packet
protection keys until they discard old keys so that only two sets of
receive keys need to be retained at any point in time.
Paragraph (version B):
QUIC Error Codes Registry QUIC-TRANSPORT - IANA is to register the
KEY_UPDATE_ERROR (0xE), as described in key-update-error.