diff --git a/draft-ietf-quic-recovery.md b/draft-ietf-quic-recovery.md index 08e03c4a88..0f4162fbf2 100644 --- a/draft-ietf-quic-recovery.md +++ b/draft-ietf-quic-recovery.md @@ -90,29 +90,28 @@ when, and only when, they appear in all capitals, as shown here. # Design of the QUIC Transmission Machinery All transmissions in QUIC are sent with a packet-level header, which indicates -the encryption level and includes a packet sequence number -(referred to below as a packet number). The encryption level indicates the -packet number space, as described in {{QUIC-TRANSPORT}}. Packet -numbers never repeat within a packet number space for the lifetime of a -connection. Packet numbers monotonically increase within a space, -preventing ambiguity. +the encryption level and includes a packet sequence number (referred to below as +a packet number). The encryption level indicates the packet number space, as +described in {{QUIC-TRANSPORT}}. Packet numbers never repeat within a packet +number space for the lifetime of a connection. Packet numbers monotonically +increase within a space, preventing ambiguity. -This design obviates the need for disambiguating between transmissions -and retransmissions and eliminates significant complexity from QUIC's -interpretation of TCP loss detection mechanisms. +This design obviates the need for disambiguating between transmissions and +retransmissions and eliminates significant complexity from QUIC's interpretation +of TCP loss detection mechanisms. Every packet may contain several frames. We outline the frames that are important to the loss detection and congestion control machinery below. -* Retransmittable frames are those that count towards bytes in - flight and need acknowledgement. The most common are STREAM frames, - which typically contain application data. +* Retransmittable frames are those that count towards bytes in flight and need + acknowledgement. The most common are STREAM frames, which typically contain + application data. -* Retransmittable packets are those that contain at least one - retransmittable frame. +* Retransmittable packets are those that contain at least one retransmittable + frame. -* Crypto handshake data is sent in CRYPTO_HS frames, and uses the reliability - machinery of QUIC underneath. +* Cryptographic handshake data is sent in CRYPTO frames, and uses the + reliability machinery of QUIC underneath. * ACK and ACK_ECN frames contain acknowledgment information. ACK_ECN frames additionally contain information about ECN codepoints seen by the peer. (The @@ -128,22 +127,22 @@ these protocol differences below. ### Separate Packet Number Spaces -QUIC uses separate packet number spaces for each encryption level, except -0-RTT and all generations of 1-RTT keys use the same packet number space. -Separate packet number spaces ensures acknowledgement of packets sent -with one level of encryption will not cause spurious retransmission of packets -sent with a different encryption level. Congestion control and RTT measurement -are unified across packet number spaces. +QUIC uses separate packet number spaces for each encryption level, except 0-RTT +and all generations of 1-RTT keys use the same packet number space. Separate +packet number spaces ensures acknowledgement of packets sent with one level of +encryption will not cause spurious retransmission of packets sent with a +different encryption level. Congestion control and RTT measurement are unified +across packet number spaces. ### Monotonically Increasing Packet Numbers TCP conflates transmission sequence number at the sender with delivery sequence number at the receiver, which results in retransmissions of the same data carrying the same sequence number, and consequently to problems caused by -"retransmission ambiguity". QUIC separates the two: QUIC uses a packet -number for transmissions, and any data that is to be delivered to the receiving -application(s) is sent in one or more streams, with delivery order determined -by stream offsets encoded within STREAM frames. +"retransmission ambiguity". QUIC separates the two: QUIC uses a packet number +for transmissions, and any data that is to be delivered to the receiving +application(s) is sent in one or more streams, with delivery order determined by +stream offsets encoded within STREAM frames. QUIC's packet number is strictly increasing, and directly encodes transmission order. A higher QUIC packet number signifies that the packet was sent later, @@ -191,21 +190,20 @@ round-trip time (RTT) is critical to these algorithms and is described first. ## Computing the RTT estimate -RTT is calculated when an ACK frame arrives by computing the difference -between the current time and the time the largest newly acked packet was sent. -If no packets are newly acknowledged, RTT cannot be calculated. When RTT is -calculated, the ack delay field from the ACK frame SHOULD be subtracted from -the RTT as long as the result is larger than the Min RTT. If the result is -smaller than the min_rtt, the RTT should be used, but the ack delay field -should be ignored. +RTT is calculated when an ACK frame arrives by computing the difference between +the current time and the time the largest newly acked packet was sent. If no +packets are newly acknowledged, RTT cannot be calculated. When RTT is +calculated, the ack delay field from the ACK frame SHOULD be subtracted from the +RTT as long as the result is larger than the Min RTT. If the result is smaller +than the min_rtt, the RTT should be used, but the ack delay field should be +ignored. Like TCP, QUIC calculates both smoothed RTT and RTT variance similar to those specified in {{?RFC6298}}. -Min RTT is the minimum RTT measured over the connection, prior to adjusting -by ack delay. Ignoring ack delay for min RTT prevents intentional or -unintentional underestimation of min RTT, which in turn prevents -underestimating smoothed RTT. +Min RTT is the minimum RTT measured over the connection, prior to adjusting by +ack delay. Ignoring ack delay for min RTT prevents intentional or unintentional +underestimation of min RTT, which in turn prevents underestimating smoothed RTT. ## Ack-based Detection @@ -239,15 +237,14 @@ and implementers are encouraged to explore this space. ### Early Retransmit Unacknowledged packets close to the tail may have fewer than -kReorderingThreshold retransmittable packets sent after them. -Loss of such packets cannot be detected via Fast Retransmit. To enable -ack-based loss detection of such packets, receipt of an acknowledgment for the -last outstanding retransmittable packet triggers the Early Retransmit -process, as follows. - -If there are unacknowledged retransmittable packets still pending, they -should be marked as lost. To compensate for the reduced reordering resilience, -the sender SHOULD set an alarm for a small period of time. If the unacknowledged +kReorderingThreshold retransmittable packets sent after them. Loss of such +packets cannot be detected via Fast Retransmit. To enable ack-based loss +detection of such packets, receipt of an acknowledgment for the last outstanding +retransmittable packet triggers the Early Retransmit process, as follows. + +If there are unacknowledged retransmittable packets still pending, they should +be marked as lost. To compensate for the reduced reordering resilience, the +sender SHOULD set an alarm for a small period of time. If the unacknowledged retransmittable packets are not acknowledged during this time, then these packets MUST be marked as lost. @@ -257,11 +254,11 @@ than 1.25 * max(SRTT, latest_RTT) since when it was sent. Using max(SRTT, latest_RTT) protects from the two following cases: * the latest RTT sample is lower than the SRTT, perhaps due to reordering where -packet whose ack triggered the Early Retransit process encountered a shorter -path; + packet whose ack triggered the Early Retransit process encountered a shorter + path; * the latest RTT sample is higher than the SRTT, perhaps due to a sustained -increase in the actual RTT, but the smoothed SRTT has not yet caught up. + increase in the actual RTT, but the smoothed SRTT has not yet caught up. The 1.25 multiplier increases reordering resilience. Implementers MAY experiment with using other multipliers, bearing in mind that a lower multiplier reduces @@ -276,36 +273,35 @@ alarm for TCP as well, and this document incorporates this advancement. ## Timer-based Detection -Timer-based loss detection implements a handshake retransmission timer that -is optimized for QUIC as well as the spirit of TCP's Tail Loss Probe -and Retransmission Timeout mechanisms. +Timer-based loss detection implements a handshake retransmission timer that is +optimized for QUIC as well as the spirit of TCP's Tail Loss Probe and +Retransmission Timeout mechanisms. ### Crypto Handshake Timeout -Data in CRYPTO_HS frames is critical to QUIC transport and crypto negotiation, -so a more aggressive timeout is used to retransmit it. Below, the word -handshake packet is used to refer to packets containing CRYPTO_HS frames, -not packets with the specific long header packet type Handshake. +Data in CRYPTO frames is critical to QUIC transport and crypto negotiation, so a +more aggressive timeout is used to retransmit it. Below, the term "handshake +packet" is used to refer to packets containing CRYPTO frames, not packets with +the specific long header packet type Handshake. The initial handshake timeout SHOULD be set to twice the initial RTT. -At the beginning, there are no prior RTT samples within a connection. -Resumed connections over the same network SHOULD use the previous -connection's final smoothed RTT value as the resumed connection's initial RTT. +At the beginning, there are no prior RTT samples within a connection. Resumed +connections over the same network SHOULD use the previous connection's final +smoothed RTT value as the resumed connection's initial RTT. If no previous RTT is available, or if the network changes, the initial RTT SHOULD be set to 100ms. -When CRYPTO_HS frames are sent, the sender SHOULD set an alarm for the -handshake timeout period. When the alarm fires, the sender MUST retransmit -all unacknowledged CRYPTO_HS data by calling -RetransmitAllUnackedHandshakeData(). On each consecutive firing of the -handshake alarm without receiving an acknowledgement for a new packet, -the sender SHOULD double the handshake timeout and set an alarm for this -period. +When CRYPTO frames are sent, the sender SHOULD set an alarm for the handshake +timeout period. When the alarm fires, the sender MUST retransmit all +unacknowledged CRYPTO data by calling RetransmitAllUnackedHandshakeData(). On +each consecutive firing of the handshake alarm without receiving an +acknowledgement for a new packet, the sender SHOULD double the handshake timeout +and set an alarm for this period. -When CRYPTO_HS frames are outstanding, the TLP and RTO timers are not active -unless the CRYPTO_HS frames were sent at 1RTT encryption. +When CRYPTO frames are outstanding, the TLP and RTO timers are not active unless +the CRYPTO frames were sent at 1RTT encryption. When an acknowledgement is received for a handshake packet, the new RTT is computed and the alarm SHOULD be set for twice the newly computed smoothed RTT. @@ -315,9 +311,9 @@ computed and the alarm SHOULD be set for twice the newly computed smoothed RTT. A Retry packet causes the content of the client's Initial packet to be immediately retransmitted along with the token present in the Retry. -The Retry indicates that the Initial was received but not processed. -It MUST NOT be treated as an acknowledgment for the Initial, -but it MAY be used for an RTT measurement. +The Retry indicates that the Initial was received but not processed. It MUST +NOT be treated as an acknowledgment for the Initial, but it MAY be used for an +RTT measurement. ### Tail Loss Probe {#tlp} @@ -327,9 +323,9 @@ algorithm proposed for TCP {{?TLP=I-D.dukkipati-tcpm-tcp-loss-probe}}. A packet sent at the tail is particularly vulnerable to slow loss detection, since acks of subsequent packets are needed to trigger ack-based detection. To ameliorate this weakness of tail packets, the sender schedules an alarm when the -last retransmittable packet before quiescence is transmitted. When this -alarm fires, a Tail Loss Probe (TLP) packet is sent to evoke an acknowledgement -from the receiver. +last retransmittable packet before quiescence is transmitted. When this alarm +fires, a Tail Loss Probe (TLP) packet is sent to evoke an acknowledgement from +the receiver. The alarm duration, or Probe Timeout (PTO), is set based on the following conditions: @@ -344,13 +340,13 @@ MaxAckDelay excludes ack delays that aren't included in an RTT sample because they're too large and excludes those which reference an ack-only packet. QUIC diverges from TCP by calculating MaxAckDelay dynamically, instead of -assuming a constant delayed ack timeout for all connections. QUIC includes -this in all probe timeouts, because it assume the ack delay may come into play, +assuming a constant delayed ack timeout for all connections. QUIC includes this +in all probe timeouts, because it assume the ack delay may come into play, regardless of the number of packets outstanding. TCP's TLP assumes if at least 2 packets are outstanding, acks will not be delayed. -A PTO value of at least 1.5*SRTT ensures that the ACK is overdue. The 1.5 -is based on {{?TLP}}, but implementations MAY experiment with other constants. +A PTO value of at least 1.5*SRTT ensures that the ACK is overdue. The 1.5 is +based on {{?TLP}}, but implementations MAY experiment with other constants. To reduce latency, it is RECOMMENDED that the sender set and allow the TLP alarm to fire twice before setting an RTO alarm. In other words, when the TLP alarm @@ -365,9 +361,9 @@ used to send a probe into the network prior to establishing any packet loss, prior unacknowledged packets SHOULD NOT be marked as lost when a TLP alarm fires. -A sender may not know that a packet being sent is a tail packet. -Consequently, a sender may have to arm or adjust the TLP alarm on every sent -retransmittable packet. +A sender may not know that a packet being sent is a tail packet. Consequently, +a sender may have to arm or adjust the TLP alarm on every sent retransmittable +packet. ### Retransmission Timeout {#rto} @@ -421,77 +417,73 @@ flight, since this packet adds network load without establishing packet loss. ## Generating Acknowledgements -QUIC SHOULD delay sending acknowledgements in response to packets, -but MUST NOT excessively delay acknowledgements of packets containing -non-ack frames. Specifically, implementaions MUST attempt to -enforce a maximum ack delay to avoid causing the peer spurious -timeouts. The RECOMMENDED maximum ack delay in QUIC is 25ms. +QUIC SHOULD delay sending acknowledgements in response to packets, but MUST NOT +excessively delay acknowledgements of packets containing frames other than ACK +or ACN_ECN. Specifically, implementaions MUST attempt to enforce a maximum ack +delay to avoid causing the peer spurious timeouts. The RECOMMENDED maximum ack +delay in QUIC is 25ms. -An acknowledgement MAY be sent for every second full-sized packet, -as TCP does {{?RFC5681}}, or may be sent less frequently, as long as -the delay does not exceed the maximum ack delay. QUIC recovery algorithms -do not assume the peer generates an acknowledgement immediately when -receiving a second full-sized packet. +An acknowledgement MAY be sent for every second full-sized packet, as TCP does +{{?RFC5681}}, or may be sent less frequently, as long as the delay does not +exceed the maximum ack delay. QUIC recovery algorithms do not assume the peer +generates an acknowledgement immediately when receiving a second full-sized +packet. -Out-of-order packets SHOULD be acknowledged more quickly, in order -to accelerate loss recovery. The receiver SHOULD send an immediate ACK -when it receives a new packet which is not one greater than the -largest received packet number. +Out-of-order packets SHOULD be acknowledged more quickly, in order to accelerate +loss recovery. The receiver SHOULD send an immediate ACK when it receives a new +packet which is not one greater than the largest received packet number. Similarly, packets marked with the ECN Congestion Experienced (CE) codepoint in the IP header SHOULD be acknowledged immediately, to reduce the peer's response time to congestion events. -As an optimization, a receiver MAY process multiple packets before -sending any ACK frames in response. In this case they can determine -whether an immediate or delayed acknowledgement should be generated -after processing incoming packets. +As an optimization, a receiver MAY process multiple packets before sending any +ACK frames in response. In this case they can determine whether an immediate or +delayed acknowledgement should be generated after processing incoming packets. ### Crypto Handshake Data -In order to quickly complete the handshake and avoid spurious -retransmissions due to handshake alarm timeouts, handshake packets -SHOULD use a very short ack delay, such as 1ms. ACK frames MAY be -sent immediately when the crypto stack indicates all data for that -encryption level has been received. +In order to quickly complete the handshake and avoid spurious retransmissions +due to handshake alarm timeouts, handshake packets SHOULD use a very short ack +delay, such as 1ms. ACK frames MAY be sent immediately when the crypto stack +indicates all data for that encryption level has been received. ### ACK Ranges When an ACK frame is sent, one or more ranges of acknowledged packets are -included. Including older packets reduces the chance of spurious -retransmits caused by losing previously sent ACK frames, at the cost of -larger ACK frames. +included. Including older packets reduces the chance of spurious retransmits +caused by losing previously sent ACK frames, at the cost of larger ACK frames. -ACK frames SHOULD always acknowledge the most recently received packets, -and the more out-of-order the packets are, the more important it is to send -an updated ACK frame quickly, to prevent the peer from declaring a packet -as lost and spuriusly retransmitting the frames it contains. +ACK frames SHOULD always acknowledge the most recently received packets, and the +more out-of-order the packets are, the more important it is to send an updated +ACK frame quickly, to prevent the peer from declaring a packet as lost and +spuriusly retransmitting the frames it contains. -Below is one recommended approach for determining what packets to include -in an ACK frame. +Below is one recommended approach for determining what packets to include in an +ACK frame. ### Receiver Tracking of ACK Frames -When a packet containing an ACK frame is sent, the largest acknowledged in -that frame may be saved. When a packet containing an ACK frame is -acknowledged, the receiver can stop acknowledging packets less than or equal -to the largest acknowledged in the sent ACK frame. +When a packet containing an ACK frame is sent, the largest acknowledged in that +frame may be saved. When a packet containing an ACK frame is acknowledged, the +receiver can stop acknowledging packets less than or equal to the largest +acknowledged in the sent ACK frame. -In cases without ACK frame loss, this algorithm allows for a minimum of -1 RTT of reordering. In cases with ACK frame loss, this approach does not -guarantee that every acknowledgement is seen by the sender before it is no -longer included in the ACK frame. Packets could be received out of order -and all subsequent ACK frames containing them could be lost. In this case, -the loss recovery algorithm may cause spurious retransmits, but the sender -will continue making forward progress. +In cases without ACK frame loss, this algorithm allows for a minimum of 1 RTT of +reordering. In cases with ACK frame loss, this approach does not guarantee that +every acknowledgement is seen by the sender before it is no longer included in +the ACK frame. Packets could be received out of order and all subsequent ACK +frames containing them could be lost. In this case, the loss recovery algorithm +may cause spurious retransmits, but the sender will continue making forward +progress. ## Pseudocode ### Constants of interest -Constants used in loss recovery are based on a combination of RFCs, papers, -and common practice. Some may need to be changed or negotiated in order to -better suit a variety of environments. +Constants used in loss recovery are based on a combination of RFCs, papers, and +common practice. Some may need to be changed or negotiated in order to better +suit a variety of environments. kMaxTLPs (RECOMMENDED 2): : Maximum number of tail loss probes before an RTO fires. @@ -547,7 +539,7 @@ time_of_last_sent_retransmittable_packet: : The time the most recent retransmittable packet was sent. time_of_last_sent_handshake_packet: -: The time the most recent packet containing a CRYPTO_HS frame was sent. +: The time the most recent packet containing a CRYPTO frame was sent. largest_sent_packet: : The packet number of the most recently sent packet. @@ -587,13 +579,14 @@ loss_time: transmit or exceeding the reordering window in time. sent_packets: + : An association of packet numbers to information about them, including a number field indicating the packet number, a time field indicating the time a packet was sent, a boolean indicating whether the packet is ack only, and a bytes - field indicating the packet's size. sent_packets is ordered by packet - number, and packets remain in sent_packets until acknowledged or lost. - A sent_packets data structure is maintained per packet number space, and ACK - processing only applies to a single space. + field indicating the packet's size. sent_packets is ordered by packet number, + and packets remain in sent_packets until acknowledged or lost. A sent_packets + data structure is maintained per packet number space, and ACK processing only + applies to a single space. ### Initialization diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index 87f9e4d319..7fb2d6edc8 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -112,15 +112,13 @@ code and issues list for this draft can be found at # Introduction - -This document describes how QUIC {{QUIC-TRANSPORT}} is secured using -Transport Layer Security (TLS) version 1.3 {{!TLS13=I-D.ietf-tls-tls13}}. TLS -1.3 provides critical latency improvements for connection establishment -over previous versions. Absent packet loss, most new connections can be -established and secured within a single round trip; on subsequent -connections between the same client and server, the client can often -send application data immediately, that is, using a zero round trip -setup. +This document describes how QUIC {{QUIC-TRANSPORT}} is secured using Transport +Layer Security (TLS) version 1.3 {{!TLS13=I-D.ietf-tls-tls13}}. TLS 1.3 +provides critical latency improvements for connection establishment over +previous versions. Absent packet loss, most new connections can be established +and secured within a single round trip; on subsequent connections between the +same client and server, the client can often send application data immediately, +that is, using a zero round trip setup. This document describes how the standardized TLS 1.3 acts as a security component of QUIC. @@ -158,10 +156,10 @@ Internally, TLS is a layered protocol, with the structure shown below: +--------------------------------------------+ ~~~~ -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. +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. The TLS authenticated key exchange occurs between two entities: client and server. The client initiates the exchange and the server responds. If the key @@ -220,8 +218,8 @@ Data is protected using a number of encryption levels: - Handshake Keys - Application Data (1-RTT) Keys -Application data may appear only in the early data and application -data levels. Handshake and Alert messages may appear in any level. +Application data may appear only in the early data and application data +levels. Handshake and Alert messages may appear in any level. The 0-RTT handshake is only possible if the client and server have previously communicated. In the 1-RTT handshake, the client is unable to send protected @@ -233,10 +231,10 @@ server. QUIC {{QUIC-TRANSPORT}} assumes responsibility for the confidentiality and integrity protection of packets. For this it uses keys derived from a TLS 1.3 -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 below. +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 below. ~~~~ @@ -257,8 +255,8 @@ record layer, as shown below. ~~~~ -QUIC also relies on TLS 1.3 for authentication and -negotiation of parameters that are critical to security and performance. +QUIC also relies on TLS 1.3 for authentication and negotiation of parameters +that are critical to security and performance. Rather than a strict layering, these two protocols are co-dependent: QUIC uses the TLS handshake; TLS uses the reliability and ordered delivery provided by @@ -270,13 +268,12 @@ components: * The TLS component sends and receives messages via the QUIC component, with QUIC providing a reliable stream abstraction to TLS. -* The TLS component provides a series of updates to the QUIC - component, including (a) new packet protection keys to install (b) - state changes such as handshake completion, the server certificate, - etc. +* The TLS component provides a series of updates to the QUIC component, + including (a) new packet protection keys to install (b) state changes such as + handshake completion, the server certificate, etc. -{{schematic}} shows these interactions in more detail, with the QUIC -packet protection being called out specially. +{{schematic}} shows these interactions in more detail, with the QUIC packet +protection being called out specially. ~~~ +------------+ +------------+ @@ -297,52 +294,53 @@ packet protection being called out specially. ~~~ {: #schematic title="QUIC and TLS Interactions"} -Unlike TLS over TCP, QUIC applications which want to send data do not -send it through TLS "application_data" records. Rather, they send it -as QUIC STREAM frames which are then carried in QUIC packets. +Unlike TLS over TCP, QUIC applications which want to send data do not send it +through TLS "application_data" records. Rather, they send it as QUIC STREAM +frames which are then carried in QUIC packets. # Carrying TLS Messages {#carrying-tls} -QUIC carries TLS handshake data in CRYPTO_HS frames, each of which -consists of a contiguous block of handshake data identified by an -offset and length. Those frames are packaged into QUIC packets -and encrypted under the current TLS encryption level. -As with TLS over TCP, once TLS handshake data has -been delivered to QUIC, it is QUIC's responsibility to deliver it -reliably. Each chunk of data that is produced by TLS is associated -with the set of keys that TLS is currently using. If QUIC needs to -retransmit that data, it MUST use the same keys even if TLS has already -updated to newer keys. - -One important difference between TLS 1.3 records (used with TCP) -and QUIC CRYPTO_HS frames is that in QUIC multiple frames may appear -in the same QUIC packet as long as they are associated with the -same encryption level. For instance, an implementation might -bundle a Handshake message and an ACK for some Handshake +QUIC carries TLS handshake data in CRYPTO frames, each of which consists of a +contiguous block of handshake data identified by an offset and length. Those +frames are packaged into QUIC packets and encrypted under the current TLS +encryption level. As with TLS over TCP, once TLS handshake data has been +delivered to QUIC, it is QUIC's responsibility to deliver it reliably. Each +chunk of data that is produced by TLS is associated with the set of keys that +TLS is currently using. If QUIC needs to retransmit that data, it MUST use the +same keys even if TLS has already updated to newer keys. + +One important difference between TLS 1.3 records (used with TCP) and QUIC CRYPTO +frames is that in QUIC multiple frames may appear in the same QUIC packet as +long as they are associated with the same encryption level. For instance, an +implementation might bundle a Handshake message and an ACK for some Handshake data into the same packet. -Each encryption level has a specific list of frames which may appear -in it. The rules here generalize those of TLS, in that frames -associated with establishing the connection can usually appear at any -encryption level, whereas those associated with transferring data can -only appear in the 0-RTT and 1-RTT encryption levels +Each encryption level has a specific list of frames which may appear in it. The +rules here generalize those of TLS, in that frames associated with establishing +the connection can usually appear at any encryption level, whereas those +associated with transferring data can only appear in the 0-RTT and 1-RTT +encryption levels + +- CRYPTO frames MAY appear in packets of any encryption level. -- CRYPTO_HS frames MAY appear in packets of any encryption level. - CONNECTION_CLOSE MAY appear in packets of any encryption level other than 0-RTT. + - PADDING and PING frames MAY appear in packets of any encryption level. -- ACK frames MAY appear in packets of any encryption level other than - 0-RTT, but can only acknowledge packets which appeared in that - encryption level. + +- ACK frames MAY appear in packets of any encryption level other than 0-RTT, but + can only acknowledge packets which appeared in that encryption level. + - STREAM frames MUST ONLY appear in the 0-RTT and 1-RTT levels. + - All other frame types MUST only appear at the 1-RTT levels. -Because packets could be reordered on the wire, QUIC uses the packet -type to indicate which level a given packet was encrypted -under, as shown in {{packet-types-levels}}. When multiple packets of -different encryption levels need to be sent, endpoints SHOULD use -coalesced packets to send them in the same UDP datagram. +Because packets could be reordered on the wire, QUIC uses the packet type to +indicate which level a given packet was encrypted under, as shown in +{{packet-types-levels}}. When multiple packets of different encryption levels +need to be sent, endpoints SHOULD use coalesced packets to send them in the same +UDP datagram. | Packet Type | Encryption Level | PN Space | |:----------------|:-----------------|:----------| @@ -353,7 +351,7 @@ coalesced packets to send them in the same UDP datagram. | Short Header | 1-RTT | 0/1-RTT | {: #packet-types-levels title="Encryption Levels by Packet Type"} -{{QUIC-TRANSPORT}}, Section 6.3 shows how packets at the various encryption +Section 6.3 of {{QUIC-TRANSPORT}} shows how packets at the various encryption levels fit into the handshake process. ## Interface to TLS @@ -370,52 +368,46 @@ Additional functions might be needed to configure TLS. ### Sending and Receiving Handshake Messages -In order to drive the handshake, TLS depends on being able to send and -receive handshake messages. There are two basic functions on this -interface: one where QUIC requests handshake messages and one where -QUIC provides handshake packets. +In order to drive the handshake, TLS depends on being able to send and receive +handshake messages. There are two basic functions on this interface: one where +QUIC requests handshake messages and one where QUIC provides handshake packets. Before starting the handshake QUIC provides TLS with the transport parameters (see {{quic_parameters}}) that it wishes to carry. -A QUIC client starts TLS by requesting TLS handshake octets from -TLS. The client acquires handshake octets before sending its first packet. -A QUIC server starts the process by providing TLS with the client's -handshake octets. +A QUIC client starts TLS by requesting TLS handshake octets from TLS. The +client acquires handshake octets before sending its first packet. A QUIC server +starts the process by providing TLS with the client's handshake octets. At any given time, the TLS stack at an endpoint will have a current sending encryption level and receiving encryption level. Each encryption level is -associated with a different flow of bytes, which is reliably -transmitted to the peer in CRYPTO_HS frames. When TLS provides handshake -octets to be sent, they are appended to the current flow and any packet -that includes the CRYPTO_HS frame is protected using keys from the -corresponding encryption level. - -When an endpoint receives a QUIC packet containing a CRYPTO_HS frame from -the network, it proceeds as follows: - -- If the packet was in the TLS receiving encryption level, sequence - the data into the input flow as usual. As with STREAM frames, - the offset is used to find the proper location in the data sequence. - If the result of this process is that new data is available, then - it is delivered to TLS in order. - -- If the packet is from a previously installed encryption level, it - MUST not contain data which extends past the end of previously - received data in that flow. Implementations MUST treat any - violations of this requirement as a connection error of type - PROTOCOL_VIOLATION. - -- If the packet is from a new encryption level, it is saved for later - processing by TLS. Once TLS moves to receiving from this encryption - level, saved data can be provided. When providing data from any new - encryption level to TLS, if there is data from a previous encryption - level that TLS has not consumed, this MUST be treated as a connection - error of type PROTOCOL_VIOLATION. - -Each time that TLS is provided with new data, new handshake octets are -requested from TLS. TLS might not provide any octets if the handshake -messages it has received are incomplete or it has no data to send. +associated with a different flow of bytes, which is reliably transmitted to the +peer in CRYPTO frames. When TLS provides handshake octets to be sent, they are +appended to the current flow and any packet that includes the CRYPTO frame is +protected using keys from the corresponding encryption level. + +When an endpoint receives a QUIC packet containing a CRYPTO frame from the +network, it proceeds as follows: + +- If the packet was in the TLS receiving encryption level, sequence the data + into the input flow as usual. As with STREAM frames, the offset is used to + find the proper location in the data sequence. If the result of this process + is that new data is available, then it is delivered to TLS in order. + +- If the packet is from a previously installed encryption level, it MUST not + contain data which extends past the end of previously received data in that + flow. Implementations MUST treat any violations of this requirement as a + connection error of type PROTOCOL_VIOLATION. + +- If the packet is from a new encryption level, it is saved for later processing + by TLS. Once TLS moves to receiving from this encryption level, saved data + can be provided. When providing data from any new encryption level to TLS, if + there is data from a previous encryption level that TLS has not consumed, this + MUST be treated as a connection error of type PROTOCOL_VIOLATION. + +Each time that TLS is provided with new data, new handshake octets are requested +from TLS. TLS might not provide any octets if the handshake messages it has +received are incomplete or it has no data to send. Once the TLS handshake is complete, this is indicated to QUIC along with any final handshake octets that TLS needs to send. TLS also provides QUIC with the @@ -428,7 +420,7 @@ data is that the server might wish to provide additional or updated session tickets to a client. When the handshake is complete, QUIC only needs to provide TLS with any data -that arrives in CRYPTO_HS streams. In the same way that is done during the +that arrives in CRYPTO streams. In the same way that is done during the handshake, new data is requested from TLS after providing received data. Important: @@ -445,33 +437,33 @@ Important: STREAM frame that carries the Finished message in multiple packets. This enables immediate server processing for those packets. + ### Encryption Level Changes -At each change of encryption level in either direction, TLS signals -QUIC, providing the new level and the encryption keys. -These events are not asynchronous, they always occur immediately after TLS is -provided with new handshake octets, or after TLS produces handshake octets. +At each change of encryption level in either direction, TLS signals QUIC, +providing the new level and the encryption keys. These events are not +asynchronous, they always occur immediately after TLS is provided with new +handshake octets, or after TLS produces handshake octets. If 0-RTT is possible, it is ready after the client sends a TLS ClientHello message or the server receives that message. After providing a QUIC client with -the first handshake octets, the TLS stack might signal the change to -0-RTT keys. On the server, after receiving handshake octets that contain a -ClientHello message, a TLS server might signal that 0-RTT keys are available. +the first handshake octets, the TLS stack might signal the change to 0-RTT +keys. On the server, after receiving handshake octets that contain a ClientHello +message, a TLS server might signal that 0-RTT keys are available. -Note that although TLS only uses one encryption level at a time, QUIC -may use more than one level. For instance, after sending its Finished -message (using a CRYPTO_HS frame in Handshake encryption) may send STREAM -data (in 1-RTT encryption). However, if the Finished is lost, the client -would have to retransmit the Finished, in which case it would use -Handshake encryption. +Note that although TLS only uses one encryption level at a time, QUIC may use +more than one level. For instance, after sending its Finished message (using a +CRYPTO frame in Handshake encryption) may send STREAM data (in 1-RTT +encryption). However, if the Finished is lost, the client would have to +retransmit the Finished, in which case it would use Handshake encryption. ### TLS Interface Summary {{exchange-summary}} summarizes the exchange between QUIC and TLS for both -client and server. Each arrow is tagged with the encryption level used for -that transmission. +client and server. Each arrow is tagged with the encryption level used for that +transmission. ~~~ Client Server @@ -590,14 +582,13 @@ the state of all streams, including application state bound to those streams. ## HelloRetryRequest -In TLS over TCP, the HelloRetryRequest feature ({{TLS13}; Section -4.1.4) can be used to correct a client's incorrect KeyShare extension -as well as for a stateless round-trip check. From the perspective of -QUIC, this just looks like additional messages carried in the Initial -encryption level. Although it is in principle possible to use this -feature for address verification in QUIC, QUIC implementations SHOULD -instead use the Retry feature ({{QUIC-TRANSPORT}}; Section 4.4.2)). -HelloRetryRequest is still used for incorrect key shares. +In TLS over TCP, the HelloRetryRequest feature (see Section 4.1.4 of {{!TLS13}}) +can be used to correct a client's incorrect KeyShare extension as well as for a +stateless round-trip check. From the perspective of QUIC, this just looks like +additional messages carried in the Initial encryption level. Although it is in +principle possible to use this feature for address verification in QUIC, QUIC +implementations SHOULD instead use the Retry feature (see Section 4.4.2 of +{{QUIC-TRANSPORT}}). HelloRetryRequest is still used to request key shares. ## TLS Errors @@ -607,7 +598,7 @@ Section 6 of {{TLS13}}. A TLS alert is turned into a QUIC connection error by converting the one-octet alert description into a QUIC error code. The alert description is added to -0x200 to produce a QUIC error code from the range reserved for CRYPTO_ERROR. +0x100 to produce a QUIC error code from the range reserved for CRYPTO_ERROR. The resulting value is sent in a QUIC CONNECTION_CLOSE frame. The alert level of all TLS alerts is "fatal"; a TLS stack MUST NOT generate @@ -622,27 +613,23 @@ handshake, using the AEAD algorithm negotiated by TLS. ## QUIC Packet Encryption Keys {#encryption-keys} -QUIC derives packet encryption keys in the same way as TLS 1.3: -Each encryption level/direction pair has a secret value, which -is then used to derive the traffic keys using as described -in {{TLS13}}, Section 7.3. +QUIC derives packet encryption keys in the same way as TLS 1.3: Each encryption +level/direction pair has a secret value, which is then used to derive the +traffic keys using as described in Section 7.3 of {{!TLS13}} -The keys for the Initial encryption level are computed based on -the client's initial Destination Connection ID, as described in -{{initial-secrets}}. +The keys for the Initial encryption level are computed based on the client's +initial Destination Connection ID, as described in {{initial-secrets}}. -The keys for the remaining encryption level are computed in the same -fashion as the corresponding TLS keys (see {{TLS13}}; Section 7), -except that the label for HKDF-Expand-Label uses the prefix "quic " -rather than "tls13". The purpose of this change is to provide key -separation between TLS and QUIC, so that TLS stacks can avoid -exposing TLS record protection keys. +The keys for the remaining encryption level are computed in the same fashion as +the corresponding TLS keys (see Section 7 of {{!TLS13}}), except that the label +for HKDF-Expand-Label uses the prefix "quic " rather than "tls13 ". A different +label provides key separation between TLS and QUIC. ### Initial Secrets {#initial-secrets} -Initial packets are protected with -a secret derived from the Destination Connection ID field from the client's -first Initial packet of the connection. Specifically: +Initial packets are protected with a secret derived from the Destination +Connection ID field from the client's first Initial packet of the +connection. Specifically: ~~~ initial_salt = 0x9c108f98520a5c5c32968e950e8a2c5fe06d6c38 @@ -655,19 +642,18 @@ server_initial_secret = HKDF-Expand-Label(initial_secret, "server in", Hash.length) ~~~ -Note that if the server sends a Retry, the client's Initial will -correspond to a new connection and thus use the server provided -Destination Connection ID. +Note that if the server sends a Retry, the client's Initial will correspond to a +new connection and thus use the server provided Destination Connection ID. The hash function for HKDF when deriving handshake secrets and keys is SHA-256 {{!SHA=DOI.10.6028/NIST.FIPS.180-4}}. The connection ID used with HKDF-Expand-Label is the initial Destination Connection ID. -initial_salt is a 20 octet sequence shown in the figure in hexadecimal -notation. Future versions of QUIC SHOULD generate a new salt value, thus -ensuring that the keys are different for each version of QUIC. This prevents a -middlebox that only recognizes one version of QUIC from seeing or modifying the -contents of handshake packets from future versions. +The value of initial_salt is a 20 octet sequence shown in the figure in +hexadecimal notation. Future versions of QUIC SHOULD generate a new salt value, +thus ensuring that the keys are different for each version of QUIC. This +prevents a middlebox that only recognizes one version of QUIC from seeing or +modifying the contents of handshake packets from future versions. Note: @@ -690,14 +676,12 @@ QUIC packets are protected prior to applying packet number encryption (A). When removing packet protection, an endpoint first removes the protection from the packet number. -All QUIC packets other than Version Negotiation and Retry -packets are protected with an AEAD algorithm {{!AEAD}}. Prior to -establishing a shared secret, packets are protected with -AEAD_AES_128_GCM and a key derived from the destination -connection ID in the client's first Initial packet (see -{{initial-secrets}}). This provides protection against off-path -attackers and robustness against QUIC version unaware middleboxes, but -not against on-path attackers. +All QUIC packets other than Version Negotiation and Retry packets are protected +with an AEAD algorithm {{!AEAD}}. Prior to establishing a shared secret, packets +are protected with AEAD_AES_128_GCM and a key derived from the destination +connection ID in the client's first Initial packet (see {{initial-secrets}}). +This provides protection against off-path attackers and robustness against QUIC +version unaware middleboxes, but not against on-path attackers. All ciphersuites currently defined for TLS 1.3 - and therefore QUIC - have a 16-byte authentication tag and produce an output 16 bytes larger than their @@ -723,6 +707,7 @@ same key and IV (see for example {{AEBounds}}). This might be lower than the packet number limit. An endpoint MUST initiate a key update ({{key-update}}) prior to exceeding any limit set for the AEAD that is in use. + ## Packet Number Protection {#pn-encrypt} QUIC packet numbers are protected using a key that is derived from the current @@ -734,12 +719,12 @@ Packet number protection is applied after packet protection is applied (see {{aead}}). The ciphertext of the packet is sampled and used as input to an encryption algorithm. -In sampling the packet ciphertext, the packet number length is assumed to be -4 octets (its maximum possible encoded length), unless there is insufficient -space in the packet for sampling. The sampled ciphertext starts after allowing -for a 4 octet packet number unless this would cause the sample to extend past -the end of the packet. If the sample would extend past the end of the packet, -the end of the packet is sampled. +In sampling the packet ciphertext, the packet number length is assumed to be 4 +octets (its maximum possible encoded length), unless there is insufficient space +in the packet for sampling. The sampled ciphertext starts after allowing for a +4 octet packet number unless this would cause the sample to extend past the end +of the packet. If the sample would extend past the end of the packet, the end +of the packet is sampled. For example, the sampled ciphertext for a packet with a short header can be determined by: @@ -763,11 +748,11 @@ sample_offset = 6 + len(destination_connection_id) + ~~~ To ensure that this process does not sample the packet number, packet number -protection algorithms MUST NOT sample more ciphertext than the minimum -expansion of the corresponding AEAD. +protection algorithms MUST NOT sample more ciphertext than the minimum expansion +of the corresponding AEAD. -Packet number protection is applied to the packet number encoded as described -in Section 4.8 of {{QUIC-TRANSPORT}}. Since the length of the packet number is +Packet number protection is applied to the packet number encoded as described in +Section 4.8 of {{QUIC-TRANSPORT}}. Since the length of the packet number is stored in the first octet of the encoded packet number, it may be necessary to progressively decrypt the packet number. @@ -817,13 +802,12 @@ encrypted_pn = ChaCha20(pn_key, counter, nonce, packet_number) ## Receiving Protected Packets -Once an endpoint successfully receives a packet with a given packet -number, it MUST discard all packets in the same packet number space -with higher packet numbers if they cannot be successfully unprotected -with either the same key, or - if there is a key update - the next -packet protection key (see {{key-update}}). Similarly, a packet that -appears to trigger a key update, but cannot be unprotected -successfully MUST be discarded. +Once an endpoint successfully receives a packet with a given packet number, it +MUST discard all packets in the same packet number space with higher packet +numbers if they cannot be successfully unprotected with either the same key, or +- if there is a key update - the next packet protection key (see +{{key-update}}). Similarly, a packet that appears to trigger a key update, but +cannot be unprotected successfully MUST be discarded. Failure to unprotect a packet does not necessarily indicate the existence of a protocol error in a peer or an attack. The truncated packet number encoding @@ -847,10 +831,9 @@ server can send 0-RTT data until it receives all of the server's handshake messages. A client SHOULD stop sending 0-RTT data if it receives an indication that 0-RTT data has been rejected. -A server MUST NOT use 0-RTT keys to protect packets; it uses 1-RTT -keys to protect acknowledgements of 0-RTT packets. Clients MUST NOT -attempt to decrypt 0-RTT packets it receives and instead MUST discard -them. +A server MUST NOT use 0-RTT keys to protect packets; it uses 1-RTT keys to +protect acknowledgements of 0-RTT packets. Clients MUST NOT attempt to decrypt +0-RTT packets it receives and instead MUST discard them. Note: @@ -866,41 +849,39 @@ Note: 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. However, -a server MUST NOT process data from incoming 1-RTT protected packets +decrypt 1-RTT packets from the client. + +However, a server MUST NOT process data from incoming 1-RTT protected packets before verifying either the client Finished message or - in the case that the server has chosen to use a pre-shared key - the pre-shared key binder (see -Section 4.2.8 of {{!TLS13}}). Verifying these values provides the server with -an assurance that the ClientHello has not been modified. -Packets protected with 1-RTT keys MAY be stored and later decrypted and used -once the handshake is complete. +Section 4.2.11 of {{!TLS13}}). Verifying these values provides the server with +an assurance that the ClientHello has not been modified. Packets protected with +1-RTT keys MAY be stored and later decrypted and used once the handshake is +complete. A server could receive packets protected with 0-RTT keys prior to receiving a TLS ClientHello. The server MAY retain these packets for later decryption in anticipation of receiving a ClientHello. - # Key Update -Once the 1-RTT keys are established and the short header is in use, it -is possible to update the keys. The KEY_PHASE bit in the short header -is used to indicate whether key updates have occurred. The KEY_PHASE -bit is initially set to 0 and then inverted with each key update -{{key-update}}. +Once the 1-RTT keys are established and the short header is in use, it is +possible to update the keys. The KEY_PHASE bit in the short header is used to +indicate whether key updates have occurred. The KEY_PHASE bit is initially set +to 0 and then inverted with each key update {{key-update}}. -The KEY_PHASE bit allows a recipient to detect a change in keying -material without necessarily needing to receive the first packet that -triggered the change. An endpoint that notices a changed KEY_PHASE -bit can update keys and decrypt the packet that contains the changed -bit, see {{key-update}}. +The KEY_PHASE bit allows a recipient to detect a change in keying material +without necessarily needing to receive the first packet that triggered the +change. An endpoint that notices a changed KEY_PHASE bit can update keys and +decrypt the packet that contains the changed bit, see {{key-update}}. An endpoint MUST NOT initiate more than one key update at a time. A new key cannot be used until the endpoint has received and successfully decrypted a packet with a matching KEY_PHASE. A receiving endpoint detects an update when the KEY_PHASE bit doesn't match what -it is expecting. It creates a new secret (see {{TLS13}}; Section 7.2) and the +it is expecting. It creates a new secret (see Section 7.2 of {{TLS13}}) and the corresponding read key and IV. If the packet can be decrypted and authenticated using these values, then the keys it uses for packet protection are also updated. The next packet sent by the endpoint will then use the new keys. @@ -947,22 +928,21 @@ 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. + # Security of Initial Messages -Because the Initial messages are not securely encrypted, they are subject -to potential tampering by an attacker. Some forms of tampering -- such -as modifying the TLS messages themselves -- are detectable, but some --- such as modifying ACKs -- are not. To give a concrete example, -an on-path attacker could modify the ACK to make it appear that -a packet had not been received or to create a false impression of -the state of the connection (e.g., by modifying the ACK Delay). -Implementations SHOULD use caution in relying on any data which -is contained in Initial packets that is not otherwise authenticated. +Because the Initial messages are not protected with a secret key, they are +subject to potential tampering by an attacker. Some forms of tampering -- such +as modifying the TLS messages themselves -- are detectable, but some -- such as +modifying ACKs -- are not. To give a concrete example, an on-path attacker could +modify the ACK to make it appear that a packet had not been received or to +create a false impression of the state of the connection (e.g., by modifying the +ACK Delay). Implementations SHOULD use caution in relying on any data which is +contained in Initial packets that is not otherwise authenticated. -It is also possible for the attacker to tamper with data that -is carried in Handshake packets, but because that tampering -requires modifying TLS handshake messages, that tampering will -cause the TLS handshake to fail. +It is also possible for the attacker to tamper with data that is carried in +Handshake packets, but because that tampering requires modifying TLS handshake +messages, that tampering will cause the TLS handshake to fail. # QUIC-Specific Additions to the TLS Handshake @@ -1018,11 +998,10 @@ version of QUIC defined in {{QUIC-TRANSPORT}} is used. The quic_transport_parameters extension is carried in the ClientHello and the EncryptedExtensions messages during the handshake. -While the transport parameters are technically available prior to the -completion of the handshake, they cannot be fully trusted until the -handshake completes, and reliance on them should be minimized. -However, any tampering with the parameters will cause the handshake to -fail. +While the transport parameters are technically available prior to the completion +of the handshake, they cannot be fully trusted until the handshake completes, +and reliance on them should be minimized. However, any tampering with the +parameters will cause the handshake to fail. # Security Considerations @@ -1040,13 +1019,13 @@ A small ClientHello that results in a large block of handshake messages from a server can be used in packet reflection attacks to amplify the traffic generated by an attacker. -QUIC includes three defenses against this attack. First, the packet -containing a ClientHello MUST be padded to a minimum size. Second, if -responding to an unverified source address, the server is forbidden to -send more than three UDP datagrams in its first flight ({{QUIC-TRANSPORT}}; -Section 4.4.3). Finally, because acknowledgements of Handshake packets -are authenticated, a blind attacker cannot forge them. -Put together, these defenses limit the level of amplification. +QUIC includes three defenses against this attack. First, the packet containing a +ClientHello MUST be padded to a minimum size. Second, if responding to an +unverified source address, the server is forbidden to send more than three UDP +datagrams in its first flight (see Section 4.4.3 of +{{QUIC-TRANSPORT}}). Finally, because acknowledgements of Handshake packets are +authenticated, a blind attacker cannot forge them. Put together, these defenses +limit the level of amplification. ## Peer Denial of Service {#useless} @@ -1082,16 +1061,15 @@ form: encrypted_pn = packet_number XOR PRF(pn_key, sample) ~~~ -This construction is secure against chosen plaintext attacks (IND-CPA) -{{IMC}}. +This construction is secure against chosen plaintext attacks (IND-CPA) {{IMC}}. Use of the same key and ciphertext sample more than once risks compromising packet number protection. Protecting two different packet numbers with the same key and ciphertext sample reveals the exclusive OR of those packet numbers. Assuming that the AEAD acts as a PRF, if L bits are sampled, the odds of two ciphertext samples being identical approach 2^(-L/2), that is, the birthday -bound. For the algorithms described in this document, that probability is one -in 2^64. +bound. For the algorithms described in this document, that probability is one in +2^64. Note: diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index 17be052863..e8389e454c 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -550,11 +550,10 @@ provides some level of protection against off-path attackers. ### Initial Packet {#packet-initial} -The Initial packet uses long headers with a type value of 0x7F. It -carries the first CRYPTO_HS frames sent by the client and server to -perform key exchange, and may carry ACKs in either direction. The -Initial packet is protected by Initial keys as described in -{{QUIC-TLS}}. +The Initial packet uses long headers with a type value of 0x7F. It carries the +first CRYPTO frames sent by the client and server to perform key exchange, and +may carry ACKs in either direction. The Initial packet is protected by Initial +keys as described in {{QUIC-TLS}}. The Initial packet has two additional header fields that follow the normal Long Header. @@ -580,79 +579,77 @@ Token: : An optional token blob previously received in either a Retry packet or NEW_TOKEN frame. -The client and server use the Initial packet type for any packet that -contains an initial cryptographic handshake message. In addition to -the first packet(s). This includes all cases where a new packet -containing the initial cryptographic message needs to be created, such -as the packets sent after receiving a Version Negotiation -({{packet-version}}) or Retry packet ({{packet-retry}}). +The client and server use the Initial packet type for any packet that contains +an initial cryptographic handshake message. In addition to the first +packet(s). This includes all cases where a new packet containing the initial +cryptographic message needs to be created, such as the packets sent after +receiving a Version Negotiation ({{packet-version}}) or Retry packet +({{packet-retry}}). A server sends its first Initial packet in response to a client Initial. A server may send multiple Initial packets. The cryptographic key exchange could require multiple round trips or retransmissions of this data. -The payload of an Initial packet includes a CRYPTO_HS frame (or -frames) containing a cryptographic handshake message, ACK frames, or -both. The first CRYPTO_HS frame sent always begins at an offset of 0 -(see {{handshake}}). The client's complete first message MUST fit in a -single packet (see {{handshake}}). Note that if the server sends a -HelloRetryRequest, the client will send a second Initial packet with a -CRYPTO_HS frame with an offset starting at the end of the CRYPTO_HS -stream in the first Initial. +The payload of an Initial packet includes a CRYPTO frame (or frames) containing +a cryptographic handshake message, ACK frames, or both. The first CRYPTO frame +sent always begins at an offset of 0 (see {{handshake}}). The client's complete +first message MUST fit in a single packet (see {{handshake}}). Note that if the +server sends a HelloRetryRequest, the client will send a second Initial packet +with a CRYPTO frame with an offset starting at the end of the CRYPTO stream in +the first Initial. + #### Connection IDs -When an Initial packet is sent by a client which has not previously -received a Retry packet from the server, it populates the Destination -Connection ID field with an unpredictable value. This MUST be at -least 8 octets in length. Until a packet is received from the server, -the client MUST use the same value unless it abandons the connection -attempt and starts a new one. The initial Destination Connection ID is -used to determine packet protection keys for Initial packets. +When an Initial packet is sent by a client which has not previously received a +Retry packet from the server, it populates the Destination Connection ID field +with an unpredictable value. This MUST be at least 8 octets in length. Until a +packet is received from the server, the client MUST use the same value unless it +abandons the connection attempt and starts a new one. The initial Destination +Connection ID is used to determine packet protection keys for Initial packets. The client populates the Source Connection ID field with a value of its choosing and sets the SCIL field to match. -The Destination Connection ID field in the server's Initial packet -contains a connection ID that is chosen by the recipient of the packet -(i.e., the client); the Source Connection ID includes the connection -ID that the sender of the packet wishes to use (see -{{connection-id}}). The server MUST use consistent Source Connection -IDs during the handshake. +The Destination Connection ID field in the server's Initial packet contains a +connection ID that is chosen by the recipient of the packet (i.e., the client); +the Source Connection ID includes the connection ID that the sender of the +packet wishes to use (see {{connection-id}}). The server MUST use consistent +Source Connection IDs during the handshake. + +On first receiving an Initial or Retry packet from the server, the client uses +the Source Connection ID supplied by the server as the Destination Connection ID +for subsequent packets. Once a client has received an Initial packet from the +server, it MUST discard any packet it receives with a different Source +Connection ID. -On first receiving an Initial or Retry packet from the server, the -client uses the Source Connection ID supplied by the server as the -Destination Connection ID for subsequent packets. Once a client has -received an Initial packet from the server, it MUST discard any packet -it receives with a different Source Connection ID. #### Tokens -If the client has a suitable token available from a previous connection, -it SHOULD populate the Token field. +If the client has a suitable token available from a previous connection, it +SHOULD populate the Token field. -If the client received a Retry packet from the server and sends an -Initial packet in response, then it sets the Destination Connection ID to -the value from the Source Connection ID in the Retry packet. Changing -Destination Connection ID also results in a change to the keys used to -protect the Initial packet. It also sets the Token field to the -token provided in the Retry. +If the client received a Retry packet from the server and sends an Initial +packet in response, then it sets the Destination Connection ID to the value from +the Source Connection ID in the Retry packet. Changing Destination Connection ID +also results in a change to the keys used to protect the Initial packet. It also +sets the Token field to the token provided in the Retry. -When a server receives an Initial packet with an address validation -token, it SHOULD attempt to validate it. If the token is invalid then -the server SHOULD proceed as if the client did not have a validated -address, including potentially sending a Retry. If the validation -succeeds, the server SHOULD then allow the handshake to proceed (see -{{stateless-retry}}). +When a server receives an Initial packet with an address validation token, it +SHOULD attempt to validate it. If the token is invalid then the server SHOULD +proceed as if the client did not have a validated address, including potentially +sending a Retry. If the validation succeeds, the server SHOULD then allow the +handshake to proceed (see {{stateless-retry}}). Note: -: The rationale for treating the client as unvalidated rather -than discarding the packet is that the client might have received -the token in a previous connection using the NEW_TOKEN frame, -and if the server has lost state, it might be unable to validate -the token at all, leading to connection failure if the packet -is discarded. +: The rationale for treating the client as unvalidated rather than discarding + the packet is that the client might have received the token in a previous + connection using the NEW_TOKEN frame, and if the server has lost state, it + might be unable to validate the token at all, leading to connection failure if + the packet is discarded. + +>>>>>>> Reflow paragraphs #### Starting Packet Numbers @@ -660,12 +657,13 @@ The first Initial packet contains a packet number of 0. Each packet sent after the Initial packet is associated with a packet number space and its packet number increases monotonically in that space (see {{packet-numbers}}). + #### Minimum Packet Size The payload of a UDP datagram carrying the Initial packet MUST be expanded to at least 1200 octets (see {{packetization}}), by adding PADDING frames to the -Initial packet and/or by combining the Initial packet with a 0-RTT packet -(see {{packet-coalesce}}). +Initial packet and/or by combining the Initial packet with a 0-RTT packet (see +{{packet-coalesce}}). ### Retry Packet {#packet-retry} @@ -754,8 +752,8 @@ addresses can be verified through an address validation token (delivered via a Retry packet or a NEW_TOKEN frame) or by receiving any message from the client encrypted using the Handshake keys. -The payload of this packet contains CRYPTO_HS frames and could contain PADDING, -or ACK frames. Handshake packets MAY contain CONNECTION_CLOSE frames if the +The payload of this packet contains CRYPTO frames and could contain PADDING, or +ACK frames. Handshake packets MAY contain CONNECTION_CLOSE frames if the handshake is unsuccessful. @@ -1034,7 +1032,7 @@ document. | 0x0e | PATH_CHALLENGE | {{frame-path-challenge}} | | 0x0f | PATH_RESPONSE | {{frame-path-response}} | | 0x10 - 0x17 | STREAM | {{frame-stream}} | -| 0x18 | CRYPTO_HS | {{frame-crypto}} | +| 0x18 | CRYPTO | {{frame-crypto}} | | 0x19 | NEW_TOKEN | {{frame-new-token}} | | 0x20 | ACK_ECN | {{frame-ack-ecn}} | {: #frame-types title="Frame Types"} @@ -1283,17 +1281,15 @@ solicit a list of supported versions from a server. ## Cryptographic and Transport Handshake {#handshake} -QUIC relies on a combined cryptographic and transport handshake to -minimize connection establishment latency. QUIC uses the CRYPTO_HS -frame {{frame-crypto}} to transmit the cryptographic handshake. Version -0x00000001 of QUIC uses TLS 1.3 as described in {{QUIC-TLS}}; a -different QUIC version number could indicate that a different -cryptographic handshake protocol is in use. +QUIC relies on a combined cryptographic and transport handshake to minimize +connection establishment latency. QUIC uses the CRYPTO frame {{frame-crypto}} +to transmit the cryptographic handshake. Version 0x00000001 of QUIC uses TLS +1.3 as described in {{QUIC-TLS}}; a different QUIC version number could indicate +that a different cryptographic handshake protocol is in use. -QUIC provides reliable, ordered delivery of the cryptographic -handshake data. QUIC packet protection ensures confidentiality and -integrity protection that meets the requirements of the cryptographic -handshake protocol: +QUIC provides reliable, ordered delivery of the cryptographic handshake +data. QUIC packet protection ensures confidentiality and integrity protection +that meets the requirements of the cryptographic handshake protocol: * authenticated key exchange, where @@ -1320,49 +1316,46 @@ handshake protocol: client can receive packets that are addressed with the transport address that is claimed by the client (see {{address-validation}}) -The initial CRYPTO_HS frame MUST be sent in a single packet. Any -second attempt that is triggered by address validation MUST also be -sent within a single packet. This avoids having to reassemble a -message from multiple packets. +The initial CRYPTO frame MUST be sent in a single packet. Any second attempt +that is triggered by address validation MUST also be sent within a single +packet. This avoids having to reassemble a message from multiple packets. The first client packet of the cryptographic handshake protocol MUST fit within a 1232 octet QUIC packet payload. This includes overheads that reduce the space available to the cryptographic handshake protocol. -The CRYPTO_HS frame can be sent in different packet number spaces. -CRYPTO_HS frames in each packet number space carry a separate sequence -of handshake data starting from an offset of 0. +The CRYPTO frame can be sent in different packet number spaces. CRYPTO frames +in each packet number space carry a separate sequence of handshake data starting +from an offset of 0. ## Example Handshake Flows -Details of how TLS is integrated with QUIC are provided in {{QUIC-TLS}}, -but some examples are provided here. +Details of how TLS is integrated with QUIC are provided in {{QUIC-TLS}}, but +some examples are provided here. -{{tls-1rtt-handshake}} provides an overview of the 1-RTT handshake. -Each line shows a QUIC packet with the packet type and packet -number shown first, followed by the contents. So, for instance -the first packet is of type Initial, with packet number 0, and -contains a CRYPTO_HS frame carrying the ClientHello. +{{tls-1rtt-handshake}} provides an overview of the 1-RTT handshake. Each line +shows a QUIC packet with the packet type and packet number shown first, followed +by the contents. 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 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. +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. ~~~~ Client Server -Initial[0]: CRYPTO_HS[CH] -> +Initial[0]: CRYPTO[CH] -> - Initial[0]: CRYPTO_HS[SH] ACK[0] - Handshake[0]: CRYPTO_HS[EE, CERT, CV, FIN] + Initial[0]: CRYPTO[SH] ACK[0] + Handshake[0]: CRYPTO[EE, CERT, CV, FIN] <- 1-RTT[0]: STREAM[1, "..."] Initial[1]: ACK[0] -Handshake[0]: CRYPTO_HS[FIN], ACK[0] +Handshake[0]: CRYPTO[FIN], ACK[0] 1-RTT[0]: STREAM[0, "..."], ACK[0] -> 1-RTT[1]: STREAM[55, "..."], ACK[0] @@ -1371,26 +1364,25 @@ Handshake[0]: CRYPTO_HS[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 ACKs the -0-RTT data at the 1-RTT encryption level, and the client's -sequence numbers at the 1-RTT encryption level continue -to increment from its 0-RTT packets. +{{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 ACKs the 0-RTT data at the 1-RTT encryption level, and the client's +sequence numbers at the 1-RTT encryption level continue to increment from its +0-RTT packets. ~~~~ Client Server -Initial[0]: CRYPTO_HS[CH] +Initial[0]: CRYPTO[CH] 0-RTT[0]: STREAM[0, "..."] -> - Initial[0]: CRYPTO_HS[SH] ACK[0] - Handshake[0] CRYPTO_HS[EE, CERT, CV, FIN] + Initial[0]: CRYPTO[SH] ACK[0] + Handshake[0] CRYPTO[EE, CERT, CV, FIN] <- 1-RTT[0]: STREAM[1, "..."] ACK[0] Initial[1]: ACK[0] -0-RTT[1]: CRYPTO_HS[EOED] -Handshake[0]: CRYPTO_HS[FIN], ACK[0] +0-RTT[1]: CRYPTO[EOED] +Handshake[0]: CRYPTO[FIN], ACK[0] 1-RTT[2]: STREAM[0, "..."] ACK[0] -> 1-RTT[1]: STREAM[55, "..."], ACK[1,2] @@ -3203,8 +3195,9 @@ unable to use these acknowledgments if the server cryptographic handshake messages are delayed or lost. Note that the same limitation applies to other data sent by the server protected by the 1-RTT keys. -Endpoints SHOULD send acknowledgments for packets containing CRYPTO_HS -frames with a reduced delay; see Section 3.5.1 of {{QUIC-RECOVERY}}. +Endpoints SHOULD send acknowledgments for packets containing CRYPTO frames with +a reduced delay; see Section 3.5.1 of {{QUIC-RECOVERY}}. + ## ACK_ECN Frame {#frame-ack-ecn} @@ -3406,17 +3399,16 @@ advised to bundle as few streams as necessary in outgoing packets without losing transmission efficiency to underfilled packets. -## CRYPTO_HS Frame {#frame-crypto} +## CRYPTO Frame {#frame-crypto} -The CRYPTO_HS frame (type=0x18) is used to transmit cryptographic -handshake messages. It can be sent in all packet types. The CRYPTO_HS -frame offers the cryptographic protocol an in-order stream of bytes. -CRYPTO_HS frames are functionally identical to STREAM frames, except -that they do not bear a stream identifier; they are not flow -controlled; and they do not carry markers for optional offset, -optional length, and the end of the stream. +The CRYPTO frame (type=0x18) is used to transmit cryptographic handshake +messages. It can be sent in all packet types. The CRYPTO frame offers the +cryptographic protocol an in-order stream of bytes. CRYPTO frames are +functionally identical to STREAM frames, except that they do not bear a stream +identifier; they are not flow controlled; and they do not carry markers for +optional offset, optional length, and the end of the stream. -A CRYPTO_HS frame is shown below. +A CRYPTO frame is shown below. ~~~ 0 1 2 3 @@ -3429,33 +3421,32 @@ A CRYPTO_HS frame is shown below. | Crypto Data (*) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~~~ -{: #crypto-format title="CRYPTO_HS Frame Format"} +{: #crypto-format title="CRYPTO Frame Format"} -The CRYPTO_HS frame contains the following fields: +The CRYPTO frame contains the following fields: Offset: : A variable-length integer specifying the byte offset in the stream for the - data in this CRYPTO_HS frame. + data in this CRYPTO frame. Length: : A variable-length integer specifying the length of the Crypto Data field in - this CRYPTO_HS frame. + this CRYPTO frame. Crypto Data: : The cryptographic message data. -There is a separate flow of cryptographic handshake data in each -encryption level, each of which starts at an offset of 0. This implies -that each encryption level is treated as a separate CRYPTO_HS stream -of data. +There is a separate flow of cryptographic handshake data in each encryption +level, each of which starts at an offset of 0. This implies that each encryption +level is treated as a separate CRYPTO stream of data. -Unlike STREAM frames, which include a Stream ID indicating to which -stream the data belongs, the CRYPTO_HS frame carries data for a single -stream per encryption level. The stream does not have an explicit -end, so CRYPTO_HS frames do not have a FIN bit. +Unlike STREAM frames, which include a Stream ID indicating to which stream the +data belongs, the CRYPTO frame carries data for a single stream per encryption +level. The stream does not have an explicit end, so CRYPTO frames do not have a +FIN bit. # Packetization and Reliability {#packetization} @@ -3506,10 +3497,9 @@ been lost. In general, information is sent again when a packet containing that information is determined to be lost and sending ceases when a packet containing that information is acknowledged. -* Data sent in CRYPTO_HS frames are retransmitted according to the - rules in {{QUIC-RECOVERY}}, until either all data has been - acknowledged or the crypto state machine implictly knows that the - peer received the data. +* Data sent in CRYPTO frames are retransmitted according to the rules in + {{QUIC-RECOVERY}}, until either all data has been acknowledged or the crypto + state machine implicitly knows that the peer received the data. * Application data sent in STREAM frames is retransmitted in new STREAM frames unless the endpoint has sent a RST_STREAM for that stream. Once an endpoint @@ -4145,10 +4135,10 @@ the protocol functions efficiently. That is, prioritizing frames other than STREAM frames ensures that loss recovery, congestion control, and flow control operate effectively. -CRYPTO_HS frames SHOULD be prioritized over other streams prior to the -completion of the cryptographic handshake. This includes the -retransmission of the second flight of client handshake messages, that -is, the TLS Finished and any client authentication messages. +CRYPTO frames SHOULD be prioritized over other streams prior to the completion +of the cryptographic handshake. This includes the retransmission of the second +flight of client handshake messages, that is, the TLS Finished and any client +authentication messages. STREAM data in frames determined to be lost SHOULD be retransmitted before sending new data, unless application priorities indicate otherwise. @@ -4316,9 +4306,9 @@ errors is not mandatory, but only because requiring that an endpoint generate these errors also means that the endpoint needs to maintain the final offset state for closed streams, which could mean a significant state commitment. -## Flow control of CRYPTO_HS data {#flow-control-crypto} +## Flow Control for Crytographic Handshake {#flow-control-crypto} -Data sent in CRYPTO_HS frames is not flow controlled in the same way as STREAM +Data sent in CRYPTO frames is not flow controlled in the same way as STREAM frames. QUIC relies on the cryptographic protocol implementation to avoid excessive buffering of data, see {{QUIC-TLS}}. The implementation SHOULD provide an interface to QUIC to tell it about its buffering limits so that there @@ -4350,11 +4340,11 @@ connection, MUST be signaled using a CONNECTION_CLOSE or APPLICATION_CLOSE frame ({{frame-connection-close}}, {{frame-application-close}}). An endpoint MAY close the connection in this manner even if the error only affects a single stream. -Application protocols can signal application-specific protocol errors -using the APPLICATION_CLOSE frame. Errors that are specific to the -transport, including all those described in this document, are carried -in a CONNECTION_CLOSE frame. Other than the type of error code they -carry, these frames are identical in format and semantics. +Application protocols can signal application-specific protocol errors using the +APPLICATION_CLOSE frame. Errors that are specific to the transport, including +all those described in this document, are carried in a CONNECTION_CLOSE frame. +Other than the type of error code they carry, these frames are identical in +format and semantics. A CONNECTION_CLOSE or APPLICATION_CLOSE frame could be sent in a packet that is lost. An endpoint SHOULD be prepared to retransmit a packet containing either @@ -4464,7 +4454,7 @@ INVALID_MIGRATION (0xC): : A peer has migrated to a different network when the endpoint had disabled migration. -CRYPTO_ERROR (0x2XX): +CRYPTO_ERROR (0x1XX): : The cryptographic handshake failed. A range of 256 values is reserved for carrying error codes specific to the cryptographic handshake that is used. @@ -4796,8 +4786,8 @@ Issue and pull request numbers are listed with a leading octothorp. ## Since draft-ietf-quic-transport-12 -- Enable server to transition connections to a preferred address (#560,#1251). -- Moved the cryptographic handshake off stream 0 and into CRYPTO_HS frames. +- Enable server to transition connections to a preferred address (#560, #1251). +- Moved the cryptographic handshake off stream 0 and into CRYPTO frames. - Move stateless retry to the QUIC layer. - Added token fields to Initial packet header. - Added NEW_TOKEN frame.