New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Early CONNECTION_CLOSE fixes #3440
Changes from all commits
f4c094c
68d9617
c8270f6
f01a8ee
a7f2033
032b88e
7ac257f
6492374
198883f
152a5ba
8fdeb9d
bbe18d7
a5f6205
da24edb
df917e4
1d11079
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1364,12 +1364,11 @@ by the frames that are typically contained in those packets. So, for instance | |
the first packet is of type Initial, with packet number 0, and contains a CRYPTO | ||
frame carrying the ClientHello. | ||
|
||
Note that multiple QUIC packets -- even of different encryption levels -- may be | ||
Note that multiple QUIC packets -- even of different packet types -- can be | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Take-it-or-leave-it suggestion: It seems useful to say here that different encryption levels can be coalesced. Perhaps retain this old text here? |
||
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. | ||
instance, the server's first flight contains Initial packets, | ||
Handshake packets, and "0.5-RTT data" in 1-RTT packets with a short header. | ||
|
||
~~~~ | ||
Client Server | ||
|
@@ -1390,9 +1389,9 @@ Handshake[0]: CRYPTO[FIN], ACK[0] | |
{: #tls-1rtt-handshake title="Example 1-RTT Handshake"} | ||
|
||
{{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. | ||
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. | ||
|
||
~~~~ | ||
Client Server | ||
|
@@ -2496,17 +2495,35 @@ level of packet protection to avoid the packet being discarded. After the | |
handshake is confirmed (see Section 4.1.2 of {{QUIC-TLS}}), an endpoint MUST | ||
send any CONNECTION_CLOSE frames in a 1-RTT packet. However, prior to | ||
confirming the handshake, it is possible that more advanced packet protection | ||
keys are not available to the peer, so the frame MAY be replicated in a packet | ||
that uses a lower packet protection level. | ||
keys are not available to the peer, so another CONNECTION_CLOSE frame MAY be | ||
sent in a packet that uses a lower packet protection level. More specifically: | ||
|
||
* 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. | ||
|
||
* A client that sends CONNECTION_CLOSE in a 0-RTT packet cannot be assured of | ||
the server has accepted 0-RTT and so sending a CONNECTION_CLOSE frame in an | ||
Initial packet makes it more likely that the server can receive the close | ||
signal, even if the application error code might not be received. | ||
|
||
* Prior to confirming the handshake, a peer might be unable to process 1-RTT | ||
packets, so an endpoint SHOULD send CONNECTION_CLOSE in both Handshake and | ||
1-RTT packets. A server SHOULD also send CONNECTION_CLOSE in an Initial | ||
packet. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we simplify these 3 points by just saying: |
||
|
||
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. | ||
|
||
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. Similarly, a peer might be | ||
unable to read 1-RTT packets, so an endpoint SHOULD send CONNECTION_CLOSE in | ||
Handshake and 1-RTT packets prior to confirming the handshake. These packets | ||
can be coalesced into a single UDP datagram; see {{packet-coalesce}}. | ||
CONNECTION_CLOSE frames sent in multiple packet types can be coalesced into a | ||
single UDP datagram; see {{packet-coalesce}}. | ||
|
||
|
||
## Stateless Reset {#stateless-reset} | ||
|
@@ -2841,11 +2858,10 @@ successfully authenticated. | |
|
||
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. | ||
short header are used to identify which encryption keys 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. | ||
|
||
The packet number field contains a packet number, which has additional | ||
confidentiality protection that is applied after packet protection is applied | ||
|
@@ -2870,10 +2886,11 @@ construct PMTU probes (see {{pmtu-probes-src-cid}}). Receivers MUST be able to | |
process coalesced packets. | ||
|
||
Coalescing packets in order of increasing encryption levels (Initial, 0-RTT, | ||
Handshake, 1-RTT) makes it more likely the receiver will be able to process all | ||
the packets in a single pass. A packet with a short header does not include a | ||
length, so it can only be the last packet included in a UDP datagram. An | ||
endpoint SHOULD NOT coalesce multiple packets at the same encryption level. | ||
Handshake, 1-RTT; see Section 4.1.4 of {{QUIC-TLS}}) makes it more likely the | ||
receiver will be able to process all the packets in a single pass. A packet | ||
with a short header does not include a length, so it can only be the last | ||
packet included in a UDP datagram. An endpoint SHOULD NOT coalesce multiple | ||
packets at the same encryption level. | ||
|
||
Senders MUST NOT coalesce QUIC packets for different connections into a single | ||
UDP datagram. Receivers SHOULD ignore any subsequent packets with a different | ||
|
@@ -3014,13 +3031,13 @@ frames are explained in more detail in {{frame-formats}}. | |
| 0x19 | RETIRE_CONNECTION_ID | {{frame-retire-connection-id}} | __01 | | ||
| 0x1a | PATH_CHALLENGE | {{frame-path-challenge}} | __01 | | ||
| 0x1b | PATH_RESPONSE | {{frame-path-response}} | __01 | | ||
| 0x1c - 0x1d | CONNECTION_CLOSE | {{frame-connection-close}} | IH_1* | | ||
| 0x1c - 0x1d | CONNECTION_CLOSE | {{frame-connection-close}} | ih01 | | ||
| 0x1e | HANDSHAKE_DONE | {{frame-handshake-done}} | ___1 | | ||
{: #frame-types title="Frame Types"} | ||
|
||
The "Packets" column in {{frame-types}} does not form part of the IANA registry | ||
(see {{iana-frames}}). This column lists the types of packets that each | ||
frame type can appear in, indicated by the following characters: | ||
frame type could appear in, indicated by the following characters: | ||
|
||
I: | ||
|
||
|
@@ -3038,11 +3055,10 @@ H: | |
|
||
: 1-RTT ({{short-header}}) | ||
|
||
*: | ||
ih: | ||
|
||
: A CONNECTION_CLOSE frame of type 0x1c can appear in Initial, Handshake, and | ||
1-RTT packets, whereas a CONNECTION_CLOSE of type 0x1d can only appear in a | ||
1-RTT packet. | ||
: A CONNECTION_CLOSE frame of type 0x1d cannot appear in Initial or Handshake | ||
packets. | ||
|
||
Section 4 of {{QUIC-TLS}} provides more detail about these restrictions. Note | ||
that all frames can appear in 1-RTT packets. | ||
|
@@ -3290,7 +3306,7 @@ containing that information is acknowledged. | |
* 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 encryption level are discarded. | ||
corresponding packet number space are discarded. | ||
|
||
* Application data sent in STREAM frames is retransmitted in new STREAM frames | ||
unless the endpoint has sent a RESET_STREAM for that stream. Once an endpoint | ||
|
@@ -4214,9 +4230,9 @@ PADDING, or 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. | ||
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. | ||
|
||
### Retry Packet {#packet-retry} | ||
|
||
|
@@ -5680,10 +5696,10 @@ Reason Phrase: | |
This SHOULD be a UTF-8 encoded string {{!RFC3629}}. | ||
|
||
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. | ||
sent using 0-RTT or 1-RTT packets ({{QUIC-TLS}}, Section 4). When an | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good to know that the sentence here forbids CONNECTION_CLOSE (0x1d) being used in Handshake packets. Maybe it's the case that we changed here, but not the other places (that I have pointed out). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well that was a mistake, but now I don't have to fix it :) |
||
application wishes to abandon a connection during the handshake, an endpoint | ||
can send a CONNECTION_CLOSE frame (type 0x1c) with an error code of | ||
APPLICATION_ERROR in an Initial or a Handshake packet. | ||
|
||
|
||
## HANDSHAKE_DONE frame {#frame-handshake-done} | ||
|
@@ -5789,6 +5805,10 @@ PROTOCOL_VIOLATION (0xA): | |
INVALID_TOKEN (0xB): | ||
: A server received a Retry Token in a client Initial that is invalid. | ||
|
||
APPLICATION_ERROR (0xC): | ||
|
||
: The application or application protocol caused the connection to be closed. | ||
|
||
CRYPTO_BUFFER_EXCEEDED (0xD): | ||
|
||
: An endpoint has received more data in CRYPTO frames than it can buffer. | ||
|
@@ -6575,6 +6595,7 @@ The initial contents of this registry are shown in {{iana-error-table}}. | |
| 0x9 | CONNECTION_ID_LIMIT_ERROR | Too many connection IDs received | {{error-codes}} | | ||
| 0xA | PROTOCOL_VIOLATION | Generic protocol violation | {{error-codes}} | | ||
| 0xB | INVALID_TOKEN | Invalid Token Received | {{error-codes}} | | ||
| 0xC | APPLICATION_ERROR | Application error | {{error-codes}} | | ||
| 0xD | CRYPTO_BUFFER_EXCEEDED | CRYPTO data buffer overflowed | {{error-codes}} | | ||
{: #iana-error-table title="Initial QUIC Transport Error Codes Entries"} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"application data packet number space"