Draft: draft-ietf-quic-transport

Commentary: This allows us to avoid treating 0 - RTT specially more generally . The advice on where to send CONNECTIONCLOSE seems ornate , but it reduces to " send CONNECTIONCLOSE in every space you have keys for " . The trick is that we do n't want to allow application error codes to leak in Initial ( edit : and Handshake ) packets , so this defines an error code in the transport space that says " the application decided to close the connection " . I think that this is better than relying on the proxied TLS alert code , so I changed the recommendation to use 0x15a to refer to this new APPLICATION_ERROR error code . 
 I 've updated this one to fix the other issue as well . And yes that means multiple error codes . That 's a little ugly , but otherwise we have cases where CONNECTIONCLOSE is initiated by the application in a way that the peer ca n't consume it . We either let the connection die without CONNECTIONCLOSE , do some mapping , or we leak application state into " cleartext " . I like the explicit signal . 
 can you check the recent changes here ? 
 In fixing , I realized that it was tricky to send an application - level close in 0 - RTT because of the need to potentially send a close in Initial or Handshake packets . However , the same applies to 0.5 - RTT . The client might not have 1 - RTT keys when the server sends a CONNECTION_CLOSE in a short header packet . Rather than try to remap application errors onto transport errors to solve this , just let the application signal an error any time . Sure , both 0 - RTT and 0.5 - RTT both have in common the lack of input from a peer , so signaling an error seems unnecessary , but the restriction we have only exists because we are n't sure that the condition is valid . But it might be . Imagine that an application error condition could be triggered by TLS extensions or transport parameters . Or maybe the endpoint just does n't want to continue . Lifting the restriction should simplify a lot of things . 
 I am not sure if that is the correct thing to do . IIRC , the reason we have limited use of application CONNECTION_CLOSE to 1 - RTT is because the error code is part of the application protocol , and because the role of QUIC as a transport protocol is to provide " encryption " to the application protocol . That 's what we agreed late last year , see . The flip side of allowing application close to be sent using Initial packets is that every application protocol using QUIC would be required to specify the error codes that can be sent using Initial packets or not , because the error code sent using an Initial packet would be observable . I would argue that that would be a complexity . 
 That is an entirely reasonable objection . The question then becomes : what do we do when we have a desire to signal an application - level error , but we are n't sure that the peer can receive a packet that is amply protected ? For instance , if a server accepts 0 - RTT only to find that the contents are gibberish , it might signal in a 1 - RTT packet with the appropriate application CONNECTIONCLOSE , but it has no guarantee that this will be readable to a client . I suspect that the right answer is to switch to a transport - level CONNECTIONCLOSE with a different error code in that case . Allowing application CONNECTION_CLOSE in 0 - RTT would still make sense then , if only to keep the API surface consistent . 
 Agreed . FWIW , we state the following , which I think is the right advice . When an application wishes to abandon a connection during the handshake , an endpoint can send a CONNECTIONCLOSE frame ( type 0x1c ) with an error code of 0x15a ( " usercanceled " alert ; see ) No objection from me . 
 I agree with Just use the CONNECTIONCLOSE frame with the generic usercanceled TLS alert . 
 The exception for CONNECTIONCLOSE in 0 - RTT is just odd . We currently exclude things from 0 - RTT only because they are impossible . As says , " feel free to send me a PROTOCOLVIOLATION when I send CONNECTION_CLOSE in 0 - RTT " . 
 IIRC , the rationale behind forbidding use of CONNECTIONCLOSE in a 0 - RTT packet was that the client should send CONNECTIONCLOSE in an Initial or Handshake packet . I am fine with allowing use of CONNECTION_CLOSE in 0 - RTT , as long as that advice is kept ( or stated ) . 
 After sending CONNECTIONCLOSE , the client is supposed to enter the closing state and stops responding other than to repeat the connection close . However , the server might reject 0 - RTT , in which case the server does n't know the connection has been closed . I see the principle for including it , but I agree with that we should advise clients that it 's kinder to send the CONNECTIONCLOSE at other encryption levels as well / instead to ensure the server can read it . 
 There 's already text about sending connection close in the highest encryption level the sender knows the peer can process . When 0 - RTT is sent , the client does n't know whether the server can process the packets . See text starting with " When sending CONNECTION_CLOSE , the goal is to ensure that the peer will process the frame . Generally , this means sending the frame in a packet with the highest level of packet protection to avoid the packet being discarded . " in I think the existing text advises clients not do this , but making it illegal is silly . 
 The testing of that feature is going to be interesting . Besides the case of servers that just do n't negotiate 0 - RTT because they do n't feel like it today , there is also the case of 0 - RTT packets being lost . The loss is not guaranteed to be detected before the TLS handshake complete . A bad faith server could just ignore any 0 - RTT packet that carries a connection close request , and do as if it was not received . I get the desire of treating 0 - RTT just like 1 - RTT , but the number of corner cases is going to be fun . 
 Let 's be clear : we have a problem of this shape already . A server can sent CONNECTION_CLOSE prior to confirming that the client has the keys necessary to interpret it . It might even have good cause to do so . Ignoring signals is always possible ; these signals exist largely as a courtesy , so that endpoints do n't dedicate resources to connections their peer no longer wants . 
 To add to what has pointed out , the server possibly ignoring frames contained in 0 - RTT packet is not limited to CONNECTION_CLOSE . While I have a mixed feeling about allowing most if not all 1 - RTT frames in 0 - RTT too , it is my understanding that that has been the principle we have agreed . I would very much prefer applying the principle everywhere rather than making decisions on a case - by - case basis . 
 In TLS draft , we state that all other frame types MUST only be sent in the 0 - RTT and 1 - RTT levels , then state that it is impossible to send some of those frames in 0 - RTT ( HANDSHAKEDONE , NEWTOKEN , PATHRESPONSE ,  ) . As it seems that we think use of these frames in 0 - RTT to be forbidden , I think we should be clear about that . 
 See also . 
 It seemed to me that the principle MT was espousing was that we do n't forbid any frames in 0 - RTT and just note in the draft the frames where some other rule made it impossible to send a conformant frame in 0 - RTT . 
 It 's not forbidden , it 's impossible -- or more precisely , it 's a protocol violation to send them for other reasons . HANDSHAKEDONE and NEWTOKEN frames are sent only by servers , and servers do n't send 0 - RTT . A client sending them at any time is forbidden . PATHRESPONSE is sent only in response to a PATHCHALLENGE ; PATHCHALLENGE can only be sent in 0 - RTT or 1 - RTT , and servers do n't send 0 - RTT . Therefore , the client ca n't be responding to a PATHCHALLENGE while it 's still sending 0 - RTT . RETIRECONNECTIONID ca n't retire the CID of its own packet . Until the transport parameters have been parsed , the client only has one CID for the server , so it 's illegal to retire it . Once the transport parameters have been parsed , in the " simple " handshake flow , the client should n't be sending 0 - RTT . If the handshake requires an extra round - trip , is it possible to keep sending 0 - RTT after having processed the Server Hello ? Should this update the table in 12.4 ? 
 yes , I think that is what I was saying . 
 Does that mean I ca n't send a FRAMEPARSING error ? That would complicate things quite a bit , since I 'd have to build extra tracking logic e.g. for a HANDSHAKEDONE that is not sent in 1 - RTT . 
 Why bother ? The client ca n't send HANDSHAKE_DONE , so you only need to check the role of the endpoint when receiving it . 
 I think you need both pieces of logic anyway . If a peer sends HANDSHAKEDONE in a Handshake frame , that 's an error regardless of role . You need to check the packet type on receipt . If a client sends HANDSHAKEDONE , that 's an error regardless of packet type . You need to check the peer 's role on receipt . The assertion here is that we do n't need to expand the packet type check to overlap with the role check . Then we get into discussion about which of multiple overlapping errors you should use . We 've done that already . 
 FWIW , I think is the way to go . Though to avoid confusion , I think it might be helpful to clarify what th " Packets " column means in of the transport draft . At the moment , the column is being explained as the types of packets that each frame type can appear in ( ) , but we could specifically say that it reflects the rules defined in plus prohibitions stated elsewhere . 
 Modulo clearing the reason phrase , this looks good .
Paragraph (version A):
Note that multiple QUIC packets - even of different encryption levels
- may be coalesced into a single UDP datagram (see packet-coalesce),
and so this handshake may consist of as few as 4 UDP datagrams, or
any number more.  For instance, the server's first flight contains
packets from the Initial encryption level (obfuscation), the
Handshake level, and "0.5-RTT data" from the server at the 1-RTT
encryption level.
Paragraph (version A):
tls-0rtt-handshake shows an example of a connection with a 0-RTT
handshake and a single packet of 0-RTT data.  Note that as described
in packet-numbers, the server acknowledges 0-RTT data at the 1-RTT
encryption level, and the client sends 1-RTT packets in the same
packet number space.
Paragraph (version B):
tls-0rtt-handshake shows an example of a connection with a 0-RTT
handshake and a single packet of 0-RTT data.  Note that as described
in packet-numbers, the server acknowledges 0-RTT data in 1-RTT
packets, and the client sends 1-RTT packets in the same packet number
space.
Paragraph (version B):
A client will always know whether the server has Handshake keys
(see discard-initial), but it is possible that a server does not
know whether the client has Handshake keys.  Under these
circumstances, a server SHOULD send a CONNECTION_CLOSE frame in
both Handshake and Initial packets to ensure that at least one of
them is processable by the client.
Paragraph (version B):
Sending a CONNECTION_CLOSE of type 0x1d in an Initial or Handshake
packet could expose application state or be used to alter application
state.  A CONNECTION_CLOSE of type 0x1d MUST be replaced by a
CONNECTION_CLOSE of type 0x1c when sending the frame in Initial or
Handshake packets.  Otherwise, information about the application
state might be revealed.  Endpoints MUST clear the value of the
Reason Phrase field and SHOULD use the APPLICATION_ERROR code when
converting to a CONNECTION_CLOSE of type 0x1c.
Paragraph (version B):
CONNECTION_CLOSE frames sent in multiple packet types can be
coalesced into a single UDP datagram; see packet-coalesce.
Paragraph (version A):
All other packets are protected with keys derived from the
cryptographic handshake.  The type of the packet from the long header
or key phase from the short header are used to identify which
encryption level - and therefore the keys - that are used.  Packets
protected with 0-RTT and 1-RTT keys are expected to have
confidentiality and data origin authentication; the cryptographic
handshake ensures that only the communicating endpoints receive the
corresponding keys.
Paragraph (version B):
Data sent in CRYPTO frames is retransmitted according to the rules
in QUIC-RECOVERY, until all data has been acknowledged.  Data in
CRYPTO frames for Initial and Handshake packets is discarded when
keys for the corresponding packet number space are discarded.
Paragraph (version B):
Like Initial packets (see discard-initial), data in CRYPTO frames for
Handshake packets is discarded - and no longer retransmitted - when
Handshake protection keys are discarded.
Paragraph (version B):
The application or application protocol caused the connection to
be closed.