Draft: draft-ietf-quic-tls

Commentary: We really REALLY mean it . The effect of has been to shame some implementations into the right behaviour , but on reviewing this section , it really was unambiguous . This tweaks the text slightly and adds a cautionary note , but it is otherwise unchanged other than a few editorial tweaks . 
 I know this has been discussed before - but reading the text as it is I wonder : the text mixes several different terms , seeming arbitrarily : decryption of 1 - RTT , processing of 1 - RTT , and reading 1 - RTT packets , and not using the 1 - RTT keys at all . I can see how packets MUST not be processed ahead of time , but I do n't see why the keys can not be used to qualify the packets . In fact the text says you can store 1 - RTT packets until ready , but how do you know they are indeed 1 - RTT packets if you can not use the keys in some form ? There is a related concern about timing attacks if you do not both decrypt and verify but if that is not topic here , and if it is a concern it should probably be mentioned or referenced . 
 In it 's becoming clear that some QUIC server implementations are using their 1RTT receive keys before getting CFIN , which is not supposed to happen . IMO , there are going to be plenty of hacky QUIC implementations but only a handful of TLS implementations , especially TLS implementations that have the special APIs required for QUIC . This is the narrow waist where we should enforce good behavior . Figure 5 of quic - tls shows that we should n't deliver the keys that early , but there 's no normative language . I will file a PR shortly for quic - tls that imposes this requirement , so that QUIC implementations ca n't possibly mess this up . 
 I like that this class of problem is naturally assumed to require some sort of protocol change . As I said on , maybe those implementations can fix their bug . is a pragmatic sort of fix that would make this an editorial issue . I 'd like that , but it sounds like there is a strong desire to go all nuclear on this . We should discuss that , or its spectre will haunt us . 
 I think it 's worth noting this , though I tend to agree with that we can not write this down using a normative language because that is a requirement of TLS . That said , I actually wonder if we can have a section discussing Implementation Pitfalls . TLS 1.3 has an appendix dedicated to that ( see ) , and it has been extremely helpful to me . I think it would be nice to have something like that in the QUIC drafts . 
 I 'm not sure of the rules here , but this requirement is on the QUIC - specific interfaces . People already have to modify TLS to comply with quic - tls . 
 IIUC , This requirement comes from the TLS handshake protocol defined in section 4 of RFC 8446 ( specifically , ) . TLS 1.3 , DTLS 1.3 , and QUIC all share the same handshake protocol . 
 Would n't this prevent the server from sending 0.5 RTT responses to 0 - RTT ? 
 Or , well , sending 0.5 RTT at all , not just for 0 - RTT . 
 Regardless of if we should use the normative language in QUIC - TLS , I think that RFC 8446 , Section 4.4.4 clarifies what the requirements are , i.e. : do not use the 1 - RTT keys until the Finished is received with the exception of 0 - RTT and also with the exception of 0.5 - RTT , while keeping in mind that the peer 's identity or liveness has not been asserted . 
 yeah , that makes sense thanks . 
 No , just the receive keys . 
 I understand that the key applicability is a general property of TLS1.3 ; however QUIC is the only one where the secret is actually consumed outside of TLS . quic - tls defines this interface and we have the right to impose constraints on it . 
 As said , it is not only QUIC . DTLS 1.3 also uses the TLS 1.3 handshake protocol while having a different packetization layer ( " records " in TLS term ) . That said , I am fine with letting the editors of the QUIC - TLS draft decide . 
 Calling this editorial , since it looks like it can be addressed without adding requirements . 
 Closing now that we have merged . 
 In TLS 1.3 , 1 - RTT secrets can be derived once the server finished is computed , when the handshake is half - complete . This allows the server to send application data without waiting for the client finished flight ( a feature sometimes called 0.5 - RTT in the TLS WG ) . This is safe because checking the peer 's finished message is only required for receiving , and the finished must be received before any application traffic when using the TLS record layer . In QUIC , the server may receive 1 - RTT packets before the client finished . This can happen because of packet loss , or an active adversary deliberately dropping handshake packets from the client , or because the client is malicious and does not send its finished flight at all . As far as I understand , the current QUIC spec allows the server to process the 1 - RTT packets and hand them to the application without waiting for the client finished . Doing this falls outside the scope of what is currently proved secure about the TLS handshake , and it leads to multiple problems : Deadlock when the network drops the client finished flight : see Potential to bypass client authentication requirements : if a server is configured with required client certificate authentication during the handshake ( e.g. for access control to a service ) , a client may send the request before the client finished flight . If QUIC passes the request to the application , it may incorrectly believe that the client has been authenticated . Potential for downgrade attacks : the client finished is used to explicitly authenticate the negotiation of algorithms in the handshake . Due to its defensive design , TLS 1.3 also implicitly authenticates the transcript in the transport secret derivation . However , the implicit authentication only holds for strong AEAD algorithms , whereas the explicit authentication relies on strong hash algorithms ( and/or signature , depending on the mode ) . A reliable way to prevent all of these issues is to mandate that every 1 - RTT packet sent by the client before the client finished frame is acknowledged by the server must include in the same datagram a copy of the finished packet ( the same handshake packet may be sent in multiple datagrams ) . The overhead is limited because finished messages are short , so even with the overhead of the long packet headers and AEAD tag , less than 100 bytes are used in the datagram ( leaving the rest for the 1 - RTT short packet ) . If this is done , it is possible to enforce that a server must have checked the client finished before processing 1 - RTT packets from the client . Adding a new transport - level signal for handshake confirmation ( as proposed in ) is a bad idea - in TLS , receiving the peer 's finished message IS the the explicit handshake confirmation signal ( which is why CCS is removed in 1.3 ) . Instead , QUIC should simply ensure that the signal has been received . It 's only an issue on the server side , because clients can not decrypt 1 - RTT packets without processing the server finished . 
 While this is true , I wonder if we have the issues you point out , because we prohibit the use of such packets until the server receives   . states that a server MUST NOT process data from incoming 1 - RTT protected packets before the TLS handshake is complete , where " handshake complete " is defined as when the TLS stack has both sent a Finished message and verified the peer ’s Finished message ( ) . 
 Yes , I agree that this spec is correct in that respect . However , it is clear that several implementations are not implementing this restriction correctly , which is understandable given that it requires server to actively delay processing buffered packets ( i.e. use memory resources ) . I think it is much better to enforce the correct behavior by requiring that the finished is repeated in every datagram until the handshake is confirmed by the server , because the server is guaranteed that it does not need a logic for received data that can not be passed to the application . 
 This recommendation has been made a few times , but we have thus far resisted it on the basis of it not working with client authentication . The suggestion that the server might offer proof that it did n't do something bad is new . If I were inclined to take that suggestion seriously , I would instead say that the server should use an exporter to generate something . You could even see how this might make its way into the proposed HANDSHAKE_DONE frame . But I do n't think that this needs this level of mechanism . This is something that servers just need to do on their own . Just like having a good source of randomness for their key generation , the consequences of failure here are that they might be open to attack . I have no problem with test suites that purposefully " drop " critical packets to reveal misbehaving servers . That might be better than adding mechanism . That said , the server can just withhold ACK frames until it sees the whole handshake , even if it processes the entire handshake . A server could answer requests from 1 - RTT until clients start looking for that happening . Ultimately , we ca n't stop the server from performing processing if it offers no reliable proof of that happening . And I do n't think that it 's worth trying . 
 To help decide whether this is likely to be a problem , I decided to run an experiment . I wrote a very simple patch to OpenSSL to disable sending a finished : I checked with to check that the patch works as expected . Then , I tried to connect to various public h3 - 23 endpoints listed on using the ngtcp2 client built with my patched OpenSSL . The point of the experiment is to check which servers would acknowledge the short packets that I sent . Note that there can be false negatives in this experiment if the server is passing the 1 - RTT data to the application but withholding the ACKS ( this is insecure because the application may make unsafe side effects based on the received data , e.g. a POST / DELETE request ) . Two servers on the list clearly implement a wrong behavior : straight up acknowledged the 1 - RTT packet in a short packethttp3- acknowledges the client 1 - RTT packet , but does that in an handshake packet ( ! ) It seems very likely that some implementations will ignore this requirement in practice ( and understandably so , as buffering the 1 - RTT packets is expensive ) , to the point that I think it is worth making the correct behavior verifiable by the client ( as it somewhat exposes the client in the downgrade case , although a complete exploit seems unlikely with a signature , and difficult with a PSK binder ) 
 In hindsight , the keyschedule for TLS 1.3 might have derived clientapplicationtrafficsecret0 from the same handshake context as resumptionmastersecret . Maybe in TLS 1.4 ? ;) 
 Yes ... the reason it ca n't ( currently ) is because finished keys are derived from traffic secrets ( which is also a mistake , especially when different transports use separate traffic secrets ) . Without changing the 1.3 key schedule QUIC could use the exporter MS to derive the client 1 - RTT traffic secret . 
 Thank you for sharing the results . This is very interesting . FWIW , I do not think QUIC stacks using picotls would have the issue , as picotls hands out the 1 - RTT read key only after processing ClientFinished ... but I can see that the API might vary between the TLS stacks . Though , if we are to have a protocol design that enforces the server to wait for CF , just bundling CF in every 1 - RTT packet is not enough . I 'd argue that CF should include some bits that is unpredictable by the server . 
 Like our TLS does n't even deliver the receive keys until it gets Finished . Rather than mess with the spec or rely on various QUIC implementations to do it right , I think it 's best to fix the various TLS implementations ( or , more specifically , their QUIC - facing secret export API ) to do this correctly . There are relatively few of these and it 's a problem specific to TLS 1.3 . The ability to coalesce sent packets is optional and the spec goes to great pains to not require sending them at any point , which has caused much suffering for Moreover , I am not at all convinced that coalescing Finished solves the problem . 
 This might be receptive to an interop - level test . Dropping Handshake packets from the client should lead to a situation where the client provides ample temptation for the server to break this rule . 
 How does this help ? Ca n't the exporter MS derived at the same time as the traffic secrets ? 
 My bad for leading you astray there . I forgot that only the resumption secret is spun off after the client Finished . Yes , an exporter does n't help . ( As an aside , I 'm fairly made exporters that way to allow them to be used with QUIC . Bit of a fail there in retrospect . ) 
 Sorry , for some reason I was convinced that exporter master includes client finished , but after double checking , this is only the case of resumption master ( honestly I think this is wrong because exporter are used for binding authentication and they pretty much fail at binding client authentication . I would suggest this is fixed in future TLS ) . 
 I agree , coalescing Finished is just a way to avoid server being blocked . The proper fix to the problem is to ensure that the client traffic secret for 1 - RTT is derived from a transcript that includes client finished , as Subodh suggests . Unfortunately , only the TLS resumption master secret includes it . 
 Would it be unreasonable to derive the client 's 1 - RTT send key from the resumption master secret then ? I guess one downside of this approach is that we 'd be using different key derivation paths for server and client , since the server needs to be able to send 0.5 - RTT data . 
 I 'd advise against doing anything like that . A change to the key schedule is very disruptive . 
 Is it disruptive because we 'd all have to update our implementations ( I imagine it would just be one more HKDF call a QUIC stack would perform when the TLS stacks hands it the 1 - RTT keys , would n't it ? ) , or are there any cryptographic reasons not to do this ? I 'm just trying to understand the issue here better , not advocating for one way or the other at this point . 
 My feeble crypto brain says it would be fine , but it feels like enough of a deviation from TLS1.3 to need a formal security analysis . 
 Figure 5 of quic - tls is pretty clear on what should happen , but I think that section could use some normative text . 
 If we did something like this , it would likely trigger completely new analysis of the protocol . The thing that concerns me is that it would reduce or eliminate key separation between resumption keys and traffic keys , which is a concern . We 'd be better off creating a new " secret " with the same transcript being input to its expansion . But that smells a lot like defining TLS 1.4 to me . 
 it 's disruptive also because of possible ongoing hardware design . That said , if it is important enough to fix ... 
 This is on purpose btw . We process the 1 - RTT packet ( as in , we decrypt it ) , but do not process the frames it contains until the handshake is complete . The reasoning behind this was to avoid having to buffer potentially invalid 1 - RTT packets . 
 If you do n't look at the frames but acknowledge the packets when do you stop buffering them ? When the server is out of memory ? 
 There 's a limit on the number of packets buffered , something like " initial congestion window"-amount of packets . 
 the transport spec says you MUST not acknowledge a packet until it 's been processed . Given you 're limiting the number of buffered packets , I do n't see any obvious gain from trying to decrypt them before buffering them . The buffer will be cleared when the handshake completes no matter what . 
 Yeah , but that does n't mean I should still buffer junk packets if I can avoid it .... 
 As for the not ackng , sure , but that 's a separate problem . 
 Agree it 's off topic , but it 's still very interesting for security research . I would never have expected implementations to do this and the security implications for stream integrity can be very surprising in some scenarios ( such as compromised PSK ) , so thanks for clarifying that . 
 can you point me where the draft says that ? I ca n't seem to be able to find it in 
 It 's the first sentence in 13.1 : " A packet MUST NOT be acknowledged until packet protection has been successfully removed and all frames contained in the packet have been processed . " 
 Sure , you ca n't ACK or process a packet before the key space is valid , but you can buffer them . There is not point in buffering garbage . Forcing keys to only be available after the key space is confirmed amounts to babysitting and there are plenty other things any endpoint can do wrong . Receiving an early ACK is ofcourse a protocol violation . 
 In interesting aside : how do you deal with   delay when you buffer packets that can not be processed yet ? 
 This feels like a great idea for Quic V2 . Instead of just having 0 - RTT and 1 - RTT packets , also define 0.5 - RTT packets that the sender can emit before the handshake is complete . ( Or maybe call them sender side 0 - RTT . ) Use different key derivations for 0.5 - RTT and for 1 - RTT , and make the 1RTT key dependent on some nonce carried with the client finished message . Add parameters somewhere ( TLS or Quic TP ) explaining whether the client will accept 0.5RTT packets or discard them . But no , not today please , not when we are finishing V1 . For V1 , we should just stick with the spec we have . 
 Discussed in Singapore ; . 
 I agree that this solves the issue IF implementations adhere to the spec . A change of the key schedule that would make it impossible to use 1 - RTT keys before the completion of the handshake would still be my preferred solution of this issue . I 'm not sure if this is n't out of scope though . Looks good . I like the idea of having normative text ( MUST NOT ) for 1 - RTT packets , because that is a QUIC - specific requirement .
Paragraph (version A):
Due to reordering and loss, protected packets might be received by an
endpoint before the final TLS handshake messages are received.  A
client will be unable to decrypt 1-RTT packets from the server,
whereas a server will be able to decrypt 1-RTT packets from the
client.
Paragraph (version B):
Due to reordering and loss, protected packets might be received by an
endpoint before the final TLS handshake messages are received.  A
client will be unable to decrypt 1-RTT packets from the server,
whereas a server will be able to decrypt 1-RTT packets from the
client.  Endpoints in either role MUST NOT decrypt 1-RTT packets from
their peer prior to completing the handshake.
Paragraph (version A):
Therefore, the server's use of 1-RTT keys is limited before the
handshake is complete.  A server MUST NOT process data from incoming
1-RTT protected packets before the TLS handshake is complete.
Because sending acknowledgments indicates that all frames in a packet
have been processed, a server cannot send acknowledgments for 1-RTT
packets until the TLS handshake is complete.  Received packets
protected with 1-RTT keys MAY be stored and later decrypted and used
once the handshake is complete.
Paragraph (version B):
Therefore, the server's use of 1-RTT keys MUST be limited to sending
data before the handshake is complete.  A server MUST NOT process
incoming 1-RTT protected packets before the TLS handshake is
complete.  Because sending acknowledgments indicates that all frames
in a packet have been processed, a server cannot send acknowledgments
for 1-RTT packets until the TLS handshake is complete.  Received
packets protected with 1-RTT keys MAY be stored and later decrypted
and used once the handshake is complete.
Paragraph (version B):
TLS implementations might provide all 1-RTT secrets prior to
handshake completion.  Even where QUIC implementations have 1-RTT
read keys, those keys cannot be used prior to completing the
handshake.