From e82b2c9174c181d4093fdf6bc1d199f6311cda19 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Thu, 20 Apr 2017 14:52:25 +1000 Subject: [PATCH 1/3] Move crypto to stream 0, HTTP control to stream 1 This doesn't fix BLOCKED, which remains a thorn in my side. That is next. --- draft-ietf-quic-http.md | 18 ++++++++--------- draft-ietf-quic-tls.md | 38 ++++++++++++++++++------------------ draft-ietf-quic-transport.md | 28 +++++++++++++------------- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/draft-ietf-quic-http.md b/draft-ietf-quic-http.md index fb8b21baa3..cc6c888f3b 100644 --- a/draft-ietf-quic-http.md +++ b/draft-ietf-quic-http.md @@ -141,7 +141,7 @@ While connection-level options pertaining to the core QUIC protocol are set in the initial crypto handshake, HTTP-specific settings are conveyed in the SETTINGS frame. After the QUIC connection is established, a SETTINGS frame ({{frame-settings}}) MUST be sent as the initial frame of the HTTP control -stream (Stream ID 3, see {{stream-mapping}}). The server MUST NOT send data on +stream (Stream ID 1, see {{stream-mapping}}). The server MUST NOT send data on any other stream until the client's SETTINGS frame has been received. ## Draft Version Identification @@ -175,8 +175,8 @@ the HTTP framing layer. A QUIC receiver buffers and orders received STREAM frames, exposing the data contained within as a reliable byte stream to the application. -QUIC reserves Stream 1 for crypto operations (the handshake, crypto config -updates). Stream 3 is reserved for sending and receiving HTTP control frames, +QUIC reserves Stream 0 for crypto operations (the handshake, crypto config +updates). Stream 1 is reserved for sending and receiving HTTP control frames, and is analogous to HTTP/2's Stream 0. This connection control stream is considered critical to the HTTP connection. If the connection control stream is closed for any reason, this MUST be treated as a connection error of type @@ -184,8 +184,8 @@ QUIC_CLOSED_CRITICAL_STREAM. When HTTP headers and data are sent over QUIC, the QUIC layer handles most of the stream management. An HTTP request/response consumes a pair of streams: This -means that the client's first request occurs on QUIC streams 5 and 7, the second -on stream 9 and 11, and so on. The server's first push consumes streams 2 and 4. +means that the client's first request occurs on QUIC streams 3 and 5, the second +on stream 7 and 9, and so on. The server's first push consumes streams 2 and 4. This amounts to the second least-significant bit differentiating the two streams in a request. @@ -222,10 +222,10 @@ responses are considered complete when the corresponding QUIC streams are closed in the appropriate direction. -## Stream 3: Connection Control Stream +## Stream 1: Connection Control Stream Since most connection-level concerns will be managed by QUIC, the primary use of -Stream 3 will be for the SETTINGS frame when the connection opens and for +Stream 1 will be for the SETTINGS frame when the connection opens and for PRIORITY frames subsequently. ## HTTP Message Exchanges @@ -373,7 +373,7 @@ corresponding data stream. # HTTP Framing Layer -Frames are used only on the connection (stream 3) and message (streams 5, 9, +Frames are used only on the connection (stream 1) and message (streams 3, 7, etc.) control streams. Other streams carry data payload and are not framed at the HTTP layer. @@ -749,7 +749,7 @@ PRIORITY frames are sent on the connection control stream and the PRIORITY section is removed from the HEADERS frame. Other than this issue, frame type HTTP/2 extensions are typically portable to -QUIC simply by replacing Stream 0 in HTTP/2 with Stream 3 in HTTP/QUIC. +QUIC simply by replacing Stream 0 in HTTP/2 with Stream 1 in HTTP/QUIC. Below is a listing of how each HTTP/2 frame type is mapped: diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index 7bce443909..742706fd8b 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -179,8 +179,8 @@ out specially. {: #schematic title="QUIC and TLS Interactions"} The initial state of a QUIC connection has packets exchanged without any form of -protection. In this state, QUIC is limited to using stream 1 and associated -packets. Stream 1 is reserved for a TLS connection. This is a complete TLS +protection. In this state, QUIC is limited to using stream 0 and associated +packets. Stream 0 is reserved for a TLS connection. This is a complete TLS connection as it would appear when layered over TCP; the only difference is that QUIC provides the reliability and ordering that would otherwise be provided by TCP. @@ -271,7 +271,7 @@ document: # TLS Usage -QUIC reserves stream 1 for a TLS connection. Stream 1 contains a complete TLS +QUIC reserves stream 0 for a TLS connection. Stream 0 contains a complete TLS connection, which includes the TLS record layer. Other than the definition of a QUIC-specific extension (see Section-TBD), TLS is unmodified for this use. This means that TLS will apply confidentiality and integrity protection to its @@ -279,7 +279,7 @@ records. In particular, TLS record protection is what provides confidentiality protection for the TLS handshake messages sent by the server. QUIC permits a client to send frames on streams starting from the first packet. -The initial packet from a client contains a stream frame for stream 1 that +The initial packet from a client contains a stream frame for stream 0 that contains the first TLS handshake messages from the client. This allows the TLS handshake to start with the first packet that a client sends. @@ -293,14 +293,14 @@ TLS, QUIC manages its own key schedule. ## Handshake and Setup Sequence The integration of QUIC with a TLS handshake is shown in more detail in -{{quic-tls-handshake}}. QUIC `STREAM` frames on stream 1 carry the TLS +{{quic-tls-handshake}}. QUIC `STREAM` frames on stream 0 carry the TLS handshake. QUIC performs loss recovery {{QUIC-RECOVERY}} for this stream and ensures that TLS handshake messages are delivered in the correct order. ~~~ Client Server -@C QUIC STREAM Frame(s) <1>: +@C QUIC STREAM Frame(s) <0>: ClientHello + QUIC Extension --------> @@ -310,7 +310,7 @@ ensures that TLS handshake messages are delivered in the correct order. Replayable QUIC Frames --------> - QUIC STREAM Frame <1>: @C + QUIC STREAM Frame <0>: @C ServerHello {TLS Handshake Messages} <-------- @@ -318,7 +318,7 @@ ensures that TLS handshake messages are delivered in the correct order. QUIC Frames @1 <-------- -@C QUIC STREAM Frame(s) <1>: +@C QUIC STREAM Frame(s) <0>: (EndOfEarlyData) {Finished} --------> @@ -371,7 +371,7 @@ Additional functions might be needed to configure TLS. ### Handshake Interface In order to drive the handshake, TLS depends on being able to send and receive -handshake messages on stream 1. There are two basic functions on this +handshake messages on stream 0. There are two basic functions on this interface: one where QUIC requests handshake messages and one where QUIC provides handshake packets. @@ -381,9 +381,9 @@ Before starting the handshake QUIC provides TLS with the transport parameters 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 stream 1 octets. +A QUIC server starts the process by providing TLS with stream 0 octets. -Each time that an endpoint receives data on stream 1, it delivers the octets to +Each time that an endpoint receives data on stream 0, it delivers the octets to TLS if it is able. 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. @@ -399,7 +399,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 on stream 1. In the same way that is done during the handshake, +that arrives on stream 0. In the same way that is done during the handshake, new data is requested from TLS after providing received data. Important: @@ -575,7 +575,7 @@ A server MUST NOT use post-handshake client authentication (see Section 4.6.2 of ## TLS Errors -Errors in the TLS connection SHOULD be signaled using TLS alerts on stream 1. A +Errors in the TLS connection SHOULD be signaled using TLS alerts on stream 0. A failure in the handshake MUST be treated as a QUIC connection error of type TLS_HANDSHAKE_FAILED. Once the handshake is complete, an error in the TLS connection that causes a TLS alert to be sent or received MUST be treated as a @@ -802,7 +802,7 @@ 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. TLS maintains a separate sequence number that is used for record protection on -the connection that is hosted on stream 1. This sequence number is not visible +the connection that is hosted on stream 0. This sequence number is not visible to QUIC. @@ -1098,7 +1098,7 @@ the overheads of that protection. # Pre-handshake QUIC Messages {#pre-hs} -Implementations MUST NOT exchange data on any stream other than stream 1 without +Implementations MUST NOT exchange data on any stream other than stream 0 without packet protection. QUIC requires the use of several types of frame for managing loss detection and recovery during this phase. In addition, it might be useful to use the data acquired during the exchange of unauthenticated messages for @@ -1149,9 +1149,9 @@ fatal error. ### STREAM Frames -`STREAM` frames for stream 1 are permitted. These carry the TLS handshake +`STREAM` frames for stream 0 are permitted. These carry the TLS handshake messages. Once 1-RTT keys are available, unprotected `STREAM` frames on stream -1 can be ignored. +0 can be ignored. Receiving unprotected `STREAM` frames for other streams MUST be treated as a fatal error. @@ -1191,12 +1191,12 @@ sources can be discarded. `MAX_DATA`, `MAX_STREAM_DATA`, `BLOCKED`, `STREAM_BLOCKED`, and `MAX_STREAM_ID` frames MUST NOT be sent unprotected. -Though data is exchanged on stream 1, the initial flow control window on that +Though data is exchanged on stream 0, the initial flow control window on that stream is sufficiently large to allow the TLS handshake to complete. This limits the maximum size of the TLS handshake and would prevent a server or client from using an abnormally large certificate chain. -Stream 1 is exempt from the connection-level flow control window. +Stream 0 is exempt from the connection-level flow control window. Consequently, there is no need to signal being blocked on flow control. diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index cdb7d6fceb..ac52310b15 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -207,11 +207,11 @@ setting up a secure transport connection. QUIC connections are expected to commonly use 0-RTT handshakes, meaning that for most QUIC connections, data can be sent immediately following the client handshake packet, without waiting for a reply from the server. QUIC -provides a dedicated stream (Stream ID 1) to be used for performing +provides a dedicated stream (Stream ID 0) to be used for performing the cryptographic handshake and QUIC options negotiation. The format of the QUIC options and parameters used during negotiation are described in this document, but the handshake protocol that runs on -Stream ID 1 is described in the accompanying cryptographic handshake +Stream ID 0 is described in the accompanying cryptographic handshake draft {{QUIC-TLS}}. ## Stream Multiplexing @@ -874,7 +874,7 @@ 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 allocates stream 1 for the cryptographic +connection establishment latency. QUIC allocates stream 0 for the cryptographic handshake. This version of QUIC uses TLS 1.3 {{QUIC-TLS}}. QUIC provides this stream with reliable, ordered delivery of data. In return, @@ -1005,9 +1005,7 @@ initial_max_stream_id (0x0002): : The initial maximum stream ID parameter contains the initial maximum stream number the peer may initiate, encoded as an unsigned 32-bit integer. This is equivalent to sending a MAX_STREAM_ID ({{frame-max-stream-id}}) immediately - after completing the handshake. This value MUST NOT be set to 0, an endpoint - MUST generate a QUIC_INVALID_NEGOTIATED_VALUE error if it receives a value of - zero for this parameter. + after completing the handshake. idle_timeout (0x0003): @@ -1671,11 +1669,13 @@ Maximum Data: connection-level data limit is determined by multiplying the encoded value by 1024. -The sum of the largest received offsets on all streams - including closed -streams - MUST NOT exceed the value advertised by a receiver. An endpoint MUST -terminate a connection with a QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA error if -it receives more data than the maximum data value that it has sent, unless this -is a result of a change in the initial limits (see {{zerortt-parameters}}). +All data sent in STREAM frames counts toward this limit, with the exception of +STREAM frames on stream 0. The sum of the largest received offsets on all +streams - including closed streams, but excluding stream 0 - MUST NOT exceed the +value advertised by a receiver. An endpoint MUST terminate a connection with a +QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA error if it receives more data than the +maximum data value that it has sent, unless this is a result of a change in the +initial limits (see {{zerortt-parameters}}). ## MAX_STREAM_DATA Frame {#frame-max-stream-data} @@ -2326,7 +2326,7 @@ ordered byte-stream. Data received out of order MUST be buffered for later delivery, as long as it is not in violation of the receiver's flow control limits. -The cryptographic handshake stream, Stream 1, MUST NOT be subject to congestion +The cryptographic handshake stream, stream 0, MUST NOT be subject to congestion control or connection-level flow control, but MUST be subject to stream-level flow control. An endpoint MUST NOT send data on any other stream without consulting the congestion controller and the flow controller. @@ -2364,7 +2364,7 @@ the protocol functions efficiently. That is, prioritizing frames other than STREAM frames ensures that loss recovery, congestion control, and flow control operate effectively. -Stream 1 MUST be prioritized over other streams prior to the completion of the +Stream 0 MUST 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. @@ -2573,7 +2573,7 @@ recoverable state, the endpoint can sent a RST_STREAM frame ({{frame-rst-stream}}) with an appropriate error code to terminate just the affected stream. -Stream 1 is critical to the functioning of the entire connection. If stream 1 +Stream 0 is critical to the functioning of the entire connection. If stream 0 is closed with either a RST_STREAM or STREAM frame bearing the FIN flag, an endpoint MUST generate a connection error of type QUIC_CLOSED_CRITICAL_STREAM. From 9e6c6d172dc0bb226d8ea54739de0dd32fd05c4c Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Thu, 27 Apr 2017 14:09:25 +1000 Subject: [PATCH 2/3] Small editorial fixes to stream identifiers --- draft-ietf-quic-transport.md | 44 ++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index ac52310b15..23ea48c665 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -1345,7 +1345,7 @@ Data Length: Stream ID: -: A variable-sized unsigned ID unique to this stream. +: The stream ID of the stream. Offset: @@ -2084,6 +2084,29 @@ similar to the way ephemeral streams are used in SST for some applications. +## Stream Identifiers {#stream-identifiers} + +Streams are identified by an unsigned 32-bit integer, referred to as the Stream +ID. To avoid Stream ID collision, clients initiate streams using odd-numbered +Stream IDs; streams initiated by the server use even-numbered Stream IDs. + +A Stream ID of zero (0x0) is reserved and used for identifying the connection as +a whole and is used in connection-level flow control frames ({{flow-control}}). +The Stream ID of zero cannot be used to establish a new stream. + +Stream ID 1 (0x1) is reserved for the cryptographic handshake. Stream ID 1 MUST +NOT be used for application data, and MUST be the first client-initiated stream. + +A QUIC endpoint cannot reuse a Stream ID. Streams MUST be created in sequential +order. Open streams can be used in any order. Streams that are used out of +order result in lower-numbered streams in the same direction being counted as +open. + +Stream IDs are usually encoded as a 32-bit integer, though the STREAM frame +({{frame-stream}}) permits a shorter encoding when the leading bits of the +stream ID are zero. + + ## Life of a Stream The semantics of QUIC streams is based on HTTP/2 streams, and the lifecycle of a @@ -2263,25 +2286,6 @@ Reordering might cause frames to be received after closing, see {{state-hc-remote}}. -## Stream Identifiers {#stream-identifiers} - -Streams are identified by an unsigned 32-bit integer, referred to as the -Stream ID. To avoid Stream ID collision, clients MUST initiate streams using -odd-numbered Stream IDs; streams initiated by the server MUST use even-numbered -Stream IDs. - -A Stream ID of zero (0x0) is reserved and used for connection-level flow control -frames ({{flow-control}}); the Stream ID of zero cannot be used to establish a -new stream. - -Stream ID 1 (0x1) is reserved for the cryptographic handshake. Stream ID 1 MUST -NOT be used for application data, and MUST be the first client-initiated stream. - -A QUIC endpoint cannot reuse a Stream ID on a given connection. Streams MUST be -created in sequential order. Open streams can be used in any order. Streams -that are used out of order result in lower-numbered streams in the same -direction being counted as open. - ## Stream Concurrency {#stream-concurrency} From c67b678b59dce1e873d588be82edb6604cfd68dc Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Fri, 28 Apr 2017 16:12:14 +1000 Subject: [PATCH 3/3] Update for crypto on stream 0 --- draft-ietf-quic-transport.md | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index 23ea48c665..cd931ff007 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -2084,18 +2084,14 @@ similar to the way ephemeral streams are used in SST for some applications. -## Stream Identifiers {#stream-identifiers} +## Stream Identifiers {#stream-id} Streams are identified by an unsigned 32-bit integer, referred to as the Stream ID. To avoid Stream ID collision, clients initiate streams using odd-numbered Stream IDs; streams initiated by the server use even-numbered Stream IDs. -A Stream ID of zero (0x0) is reserved and used for identifying the connection as -a whole and is used in connection-level flow control frames ({{flow-control}}). -The Stream ID of zero cannot be used to establish a new stream. - -Stream ID 1 (0x1) is reserved for the cryptographic handshake. Stream ID 1 MUST -NOT be used for application data, and MUST be the first client-initiated stream. +Stream ID 0 (0x0) is reserved for the cryptographic handshake. Stream 0 MUST +NOT be used for application data, and is the first client-initiated stream. A QUIC endpoint cannot reuse a Stream ID. Streams MUST be created in sequential order. Open streams can be used in any order. Streams that are used out of @@ -2175,8 +2171,8 @@ All streams start in the "idle" state. The following transitions are valid from this state: Sending or receiving a STREAM frame causes the stream to become "open". The -stream identifier is selected as described in {{stream-identifiers}}. The same -STREAM frame can also cause a stream to immediately become "half-closed". +stream identifier is selected as described in {{stream-id}}. The same STREAM +frame can also cause a stream to immediately become "half-closed". Receiving a STREAM frame on a peer-initiated stream (that is, a packet sent by a server on an even-numbered stream or a client packet on an odd-numbered stream) @@ -2854,11 +2850,11 @@ An adversarial endpoint can open lots of streams, exhausting state on an endpoint. The adversarial endpoint could repeat the process on a large number of connections, in a manner similar to SYN flooding attacks in TCP. -Normally, clients will open streams sequentially, as explained in -{{stream-identifiers}}. However, when several streams are initiated at short -intervals, transmission error may cause STREAM DATA frames opening streams to be -received out of sequence. A receiver is obligated to open intervening streams -if a higher-numbered stream ID is received. Thus, on a new connection, opening +Normally, clients will open streams sequentially, as explained in {{stream-id}}. +However, when several streams are initiated at short intervals, transmission +error may cause STREAM DATA frames opening streams to be received out of +sequence. A receiver is obligated to open intervening streams if a +higher-numbered stream ID is received. Thus, on a new connection, opening stream 2000001 opens 1 million streams, as required by the specification. The number of active streams is limited by the concurrent stream limit transport