Draft: draft-ietf-quic-tls

Commentary: As discussed in , use of application - level close is problematic in Initial / Handshake packets . This PR address the issue by limiting the use of that to 1 - RTT packets , at the same time advising applications to use user_canceled TLS alert to abort the connection during the handshake . 
 At the moment , CONNECTIONCLOSE ( 0x1d ) ( i.e. the application - level close ) is allowed " in packets of any encryption level except 0 - RTT . " ( ) . I think that it can not be sent or received in an Initial or Handshake packets , as only the QUIC and TLS are interacting at that layer . Note that the application protocol might not have been determined when Initial / Handshake packets are exchanged ( before the server returns the EE indicating which application protocol has been chosen ) . 
 Two choices : problem : let the application decide to use Handshake to abort a connection it does n't want any more . : force the application to use 1 - RTT packets to express its discontent . I can see reasons for either . 
 As stated above , I think option 1 is problematic in sense that the endpoint might not know which application protocol it is taking , though the error code being used is specific to the application protocol . Even for Handshake packets it is hard to tell if the peer has learnt the application protocol in use , as CRYPTO frames and CONNECTION_CLOSE might get delivered out of order . 
 Another issue with option 1 is that we might leak sensitive data . Consider the case where a server receives a coalesced Initial / 0 – RTT packet , and decides to respond with an application - close as the outcome of processing the 0 - RTT application data . In this case , application - close should not be sent in Initial packet , as it would be an act of an application responding to the client in cleartext . 
 I believe I prefer 2 , but if the application tries to close the connection with an application close before any data can be sent in 1 - RTT , advise the transport close the connection at Initial or Handshake instead ? I believe that both honors the intent of the application and maintains some separation . 
 Agreed . And for that purpose , I think transport close with an error code of 0x15a ( TLS alert usercanceled ) fits naturally . Quoting from , this alert notifies the recipient that the sender is canceling the handshake for some reason unrelated to a protocol failure . 
 I disagree with making a change . We discussed this exact topic when we allowed CONNECTION_CLOSE in Initial , and it was decided at the time that if an application wanted to terminate the connection at this stage , it may do so . 
 Would you mind pointing out the link to the discussion ? Besides , if we are to allow CONNECTION_CLOSE in Initial / Handshake , I think we need to clarify how an endpoint selects the error code ( see ) and how it is interpreted ( ) . I think that would be more complex to implement and maintain than limiting the use of application - level close to 1 - RTT . 
 I ca n't seem to find the discussion right now . I believe a lot of it was in person at the time as well . Things may be difficult in some scenarios , but we can leave the decision on how to handle things up to the application layer . For the 0 - RTT scenario , you can use a generic application error code . There 's no ALPN ambiguity there , right , since they have to use the same one as previous ? I do n't think we should add extra restrictions at the transport layer . 
 Would it make sense to allow connection - level CONNECTION_CLOSE in 0 - RTT , while forbidding it in Initial and Handshake ? 
 I assume you mean application - level CONNECTIONCLOSE in 0 - RTT . I do not have a strong opinion on that , though I might point out that allowing that creates a wired state ; a client would might send CONNECTIONCLOSE before it knows if the server has accepted or rejected 0 - RTT . The question here is if the client is required to retransmit CONNECTION_CLOSE in 1 - RTT when the server rejects 0 - RTT . Considering that , I think we can just forbid the use of application - close in 0 - RTT . The client can either wait for the handshake to complete then send an application - level close in 1 - RTT , or it can close the connection using a QUIC - level close during the handshake ( without exposing why ) . 
 Thank you for checking . The problem is that then there would be two requirements : Application protocols MUST define a generic error code that can be exposed unencrypted . QUIC stacks need to provide an API that tells the application if a CONNECTIONCLOSE frame is going to be sent using Initial packets . Each application needs to consult that in order to determine the error code to be sent . There is . The case is where there is an error in the 0 - RTT data that the client sends , and the server responds with a CONNECTIONCLOSE frame . In this case , there is no ambiguity on the server - side , as the server has committed to processing a particular application protocol . However , there is an issue on the client - side . The client can not tell which application protocol has been selected , as the CONNECTION_CLOSE frame ( carried in either Initial or Handshake ) may arrive before it receives the Encrypted Extensions handshake message that carries the name of the negotiated protocol . We can say that a server sending an application - level close before the client sends an 1 - RTT packet is an alternative way of negotiating the protocol . But are we really going to say that ? I think it 's too complicated . 
 I agree with there is an age old discussion on handling errors in early connection . Simply forbidding them without understanding this would be unfortunate . Consider errors in early handshake where the server does not wish to proceed . It does n't like the client , it does n't have the resources , it is about to reboot , or whatever . It can either drop the packets or wait if it can not close immediately . It does n't want to wait so it drops . Drops then probably results in unnecessary resets . 
 That 's not what this issue is about . CONNECTION_CLOSE using a transport error would still be permitted in Initial and Handshake . This is only about application - level error codes . 
 Ah I see . I agree that application errors should not happen at that level . 
 So with improved understanding , I think the correct approach is for send a PROTOCOL_VIOLATION the other direction , but since that is kind of pointless , all you can do it is to report a protocol violation the client . It would be wrong to forward the error code because that would promote bad behaviour and assumptions on application level design that might not hold in general . 
 For the first bullet , that 's a decision for the application protocols . For the second , I 'd argue you do n't need any special API . If the app terminates the connection before the " handshake complete " notification then any error code it would pass down to the QUIC API would not be sent in a 1 - RTT packet . That state is enough for the app to make an intelligent decision . Another option is to have an API flag that indicate the application close is allowed to be send unencrypted . If you assume this is not the common case , then I do n't think we need optimize for it . The app just closes the connection after the handshake completes . 
 The problem is that then there would be two requirements : Application protocols MUST define a generic error code that can be exposed unencrypted . QUIC stacks need to provide an API that tells the application if a CONNECTIONCLOSE frame is going to be sent using Initial packets . Each application needs to consult that in order to determine the error code to be sent . At the very least , the transport draft needs to suggest that , otherwise an application protocol might leak information through APPLICATIONCLOSE frames carried in Initial packets . Requiring such interaction seems more complicated than just forbidding the use of APPLICATIONCLOSE in Initial and Handshake packets in favor of CONNECTIONCLOSE(user_canceled ) . How a QUIC stack enforces that is an implementation issue , but for example , when an application instructs the QUIC stack to close the connection , the stack can decide which of the two frames to send based on the current state . I 'd dispute that this is an optimization . This is about addressing a security concern that we have so far left open . PS . I agree that  willing to postpone the closing of a connection can do so , please see the PR . 
 Maybe we need to add an API recommendation ( not requirement ) that says that " an application could be allowed to close a connection during handshake using a transport connection close frame " . This is similar to my earlier suggestion that an application could be allowed to reject incoming connections because the server is busy or whatever - this suggestion was not accepted as a requirement because it is n't necessary , but it is still a good thing to support . The question is then , how is the connection taken down - i.e. silently or with a transport close ? 
 Ok . You 've convinced me that it is just easier ( and probably safer ) to restrict application close to 1 - RTT . Though , I 'd like to point out , there 's nothing preventing an implementation from doing it anyways . 
 I agree with that observation . I think the specification does not clarify what should be done when a CONNECTIONCLOSE frame is invalid . For example , we do not define how an endpoint should react when it receives a CONNECTIONCLOSE frame with a Reason that goes beyond the end of the packet payload . I think there are two logical ways of handing the situation : a ) An endpoint that receives an invalid CONNECTIONCLOSE frame acts as if it received a valid CONNECTIONCLOSE frame . b ) An endpoint that receives an invalid CONNECTIONCLOSE frame responds with a CONNECTIONCLOSE frame carrying an appropriate error code . We can mandate either a or b , or leave it up to the implementors ( saying nothing in the text ) . Leaving it unspecified is a valid option here because the connection would promptly close regardless . Anyways , I think the problem deserves a separate issue , if some of us are interested in mandating a specific behavior . Personally , I do not care . 
 To point b ) Transport section 11.1 An endpoint that receives an invalid CONNECTION_CLOSE frame MUST NOT signal the existence of the error to its peer . 
 Clients do n't send GOAWAY and when a client sends one , the server treats it as HTTPUNEXPECTEDFRAME . By contrast , servers do n't send  but the client treats receiving one as HTTPMALFORMEDFRAME . By contrast , if GOAWAY is sent on ! control it 's HTTPUNEXPECTEDFRAME , but if  is sent on ! control , it 's HTTPWRONGSTREAM . I think the answers here are HTTPUNEXPECTEDFRAME and HTTPWRONGSTREAM respectively , but we should be consistent . 
 I think you 're correct . There are some situations where newer errors would be more appropriate .
Paragraph (version A):
CRYPTO and CONNECTION_CLOSE frames MAY appear in packets of any
encryption level except 0-RTT.
Paragraph (version B):
CRYPTO frames and CONNECTION_CLOSE frames signaling errors at the
QUIC layer (type 0x1c) MAY appear in packets of any encryption
level except 0-RTT.
Paragraph (version B):
CONNECTION_CLOSE frames signaling application errors (type 0x1d)
MUST only be sent in packets at the 1-RTT encryption level.
Paragraph (version B):
The application-specific variant of CONNECTION_CLOSE (type 0x1d) can
only be sent using an 1-RTT packet (QUIC-TLS, Section 4).  When an
application wishes to abandon a connection during the handshake, an
endpoint can send a CONNECTION_CLOSE frame (type 0x1c) with an error
code of 0x15a ("user_canceled" alert; see TLS13) in an Initial or a
Handshake packet.