Re: [quicwg/base-drafts] Stream0 dt output for merge (#1450)

Mike Bishop <notifications@github.com> Mon, 18 June 2018 22:53 UTC

Return-Path: <noreply@github.com>
X-Original-To: quic-issues@ietfa.amsl.com
Delivered-To: quic-issues@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id D392A130E4D for <quic-issues@ietfa.amsl.com>; Mon, 18 Jun 2018 15:53:05 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -8.01
X-Spam-Level:
X-Spam-Status: No, score=-8.01 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HTML_MESSAGE=0.001, MAILING_LIST_MULTI=-1, RCVD_IN_DNSWL_HI=-5, SPF_PASS=-0.001, T_DKIMWL_WL_HIGH=-0.01] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (1024-bit key) header.d=github.com
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id bpOlM-Pw0k6t for <quic-issues@ietfa.amsl.com>; Mon, 18 Jun 2018 15:52:58 -0700 (PDT)
Received: from out-4.smtp.github.com (out-4.smtp.github.com [192.30.252.195]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 5B69C130E36 for <quic-issues@ietf.org>; Mon, 18 Jun 2018 15:52:58 -0700 (PDT)
Date: Mon, 18 Jun 2018 15:52:57 -0700
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=github.com; s=pf2014; t=1529362377; bh=a5MGVkl/PO8uQ8mRHc/VIBGK5T2ayHzSvBhRyC/dGtk=; h=Date:From:Reply-To:To:Cc:In-Reply-To:References:Subject:List-ID: List-Archive:List-Post:List-Unsubscribe:From; b=CDuvMmnc+JnNFQ0QG/dGJvlveWWbZqXGL+SZFMkI9oKsQ4qGerTMxCs/Av5X8d4/e h8w5KBXSm3HQuvz+RwJEDxgcinRcsRlpIOlZ2Zm5z0ywlpMiPhetIa0I6AMF6VobIl zjGLv7aCRa+ORh7gRvsjxNneTb8SuyIJ7cfrAl9M=
From: Mike Bishop <notifications@github.com>
Reply-To: quicwg/base-drafts <reply+0166e4ab0cbeb1758c76ede030dc53d1c026306656ba1fd492cf00000001173ff9c892a169ce13d67a11@reply.github.com>
To: quicwg/base-drafts <base-drafts@noreply.github.com>
Cc: Subscribed <subscribed@noreply.github.com>
Message-ID: <quicwg/base-drafts/pull/1450/review/129681935@github.com>
In-Reply-To: <quicwg/base-drafts/pull/1450@github.com>
References: <quicwg/base-drafts/pull/1450@github.com>
Subject: Re: [quicwg/base-drafts] Stream0 dt output for merge (#1450)
Mime-Version: 1.0
Content-Type: multipart/alternative; boundary="--==_mimepart_5b2837c92f384_36672ab146dcef5c816de"; charset="UTF-8"
Content-Transfer-Encoding: 7bit
Precedence: list
X-GitHub-Sender: MikeBishop
X-GitHub-Recipient: quic-issues
X-GitHub-Reason: subscribed
X-Auto-Response-Suppress: All
X-GitHub-Recipient-Address: quic-issues@ietf.org
Archived-At: <https://mailarchive.ietf.org/arch/msg/quic-issues/wS8ZWpmGXP_Z6PGENk62c6zu72w>
X-BeenThere: quic-issues@ietf.org
X-Mailman-Version: 2.1.26
List-Id: Notification list for GitHub issues related to the QUIC WG <quic-issues.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/quic-issues>, <mailto:quic-issues-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/quic-issues/>
List-Post: <mailto:quic-issues@ietf.org>
List-Help: <mailto:quic-issues-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/quic-issues>, <mailto:quic-issues-request@ietf.org?subject=subscribe>
X-List-Received-Date: Mon, 18 Jun 2018 22:53:06 -0000

MikeBishop commented on this pull request.

Lots of editorial comments, but the content looks good.

>  
+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

Bikeshed:  I hate this name.  Why not simply CRYPTO frames or HANDSHAKE frames?  Compounding the two seems unnecessary.

> +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 is associated with the then-current TLS
+sending keys, and 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
+data into the same packet.
+
+In general, the rules for which data can appear in packets of which
+encryption level are the same in QUIC as in TLS over TCP:

This statement is confusing, as it precedes a bulleted list of things which don't exist in TLS over TCP.  Perhaps this should be reframed in terms of the types of data TLS/TCP permits, and the QUIC equivalents that carry it?

> +same encryption level. For instance, an implementation might
+bundle a Handshake message and an ACK for some Handshake
+data into the same packet.
+
+In general, the rules for which data can appear in packets of which
+encryption level are the same in QUIC as in TLS over TCP:
+
+- CRYPTO_HS frames MAY appear in packets of any encryption level.
+- CONNECTION_CLOSE and CRYPTO_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, but
+  MUST 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.

There are so many exceptions, it almost seems more efficient to indicate what frames *cannot* appear in different levels.  STREAM and flow control frames aren't permitted in Initial or Handshake; *_CLOSE aren't permitted in 0-RTT, except maybe APPLICATION_CLOSE.

>  
 ## Interface to TLS
 
-As shown in {{schematic}}, the interface from QUIC to TLS consists of four
-primary functions: Handshake, Source Address Validation, Key Ready Events, and
-Secret Export.
+As shown in {{schematic}}, the interface from QUIC to TLS consists of three
+primary functions:
+
+- Sending and receiving handshake messages
+- Rekeying (both in and out)

Perhaps "send and receive" here?  Otherwise, it could sound like the key is both coming from and being supplied to TLS.

>  
 In order to drive the handshake, TLS depends on being able to send and receive
-handshake messages on stream 0.  There are two basic functions on this
+handshake messages. There are two basic functions on this

Rewrap.

> +
+At any given time, 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
+will eventually be transmitted under the then-current key.
+
+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 current 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.

Might be worth mentioning that bytes are always provided in-order to TLS, since QUIC is otherwise permitted to support out-of-order delivery on streams.

> -request of QUIC, including the value extracted from the cookie extension.  In
-response to this request, QUIC cannot ask for client address validation, it can
-only abort or permit the connection attempt to proceed.
-
-QUIC can provide a new address validation token for use in session resumption at
-any time after the handshake is complete.  Each time a new token is provided TLS
-generates a NewSessionTicket message, with the token included in the ticket.
-
-See {{client-address-validation}} for more details on client address validation.
-
-
-### Key Ready Events
-
-TLS provides QUIC with signals when 0-RTT and 1-RTT keys are ready for use.
+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

Comma splice; either use a semicolon or divide into separate sentences.  (Though, yes, this line wasn't changed.)

>  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 that 0-RTT keys are
-ready.  On the server, after receiving handshake octets that contain a
+the first handshake octets, the TLS stack might signal the change to the
+the 0-RTT keys. On the server, after receiving handshake octets that contain a

...and I think it reads better without "the" at all.

>  ClientHello message, a TLS server might signal that 0-RTT keys are available.
 
-1-RTT keys are used for packets in both directions.  0-RTT keys are only
-used to protect packets sent by the client.
-
-
-### Secret Export
+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

May?  Will have to, I believe.

>  
-## QUIC Key Expansion {#key-expansion}
+A server rejects 0-RTT by rejecting 0-RTT at the TLS layer.  This results in
+early exporter keys being unavailable, thereby preventing the use of 0-RTT for
+QUIC.

Under this model, exporters (early or otherwise) have nothing to do with the use of a particular encryption level for QUIC, IIUC.

>  
-QUIC uses the Hash-based Key Derivation Function (HKDF) {{!HKDF=RFC5869}} with
-the same hash function negotiated by TLS for key derivation.  For example, if
-TLS is using the TLS_AES_128_GCM_SHA256, the SHA-256 hash function is used.
+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

round-trip

>  
-QUIC uses the Hash-based Key Derivation Function (HKDF) {{!HKDF=RFC5869}} with
-the same hash function negotiated by TLS for key derivation.  For example, if
-TLS is using the TLS_AES_128_GCM_SHA256, the SHA-256 hash function is used.
+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)).

Might be worth explicitly noting that this *is* still used for incorrect key shares.

>  
-~~~
-struct {
-   uint16 length = Length;
-   opaque label<6..255> = "QUIC " + Label;
-} QhkdfExpandInfo;
-~~~
+# QUIC Packet Protection {#packet-protection}
+
+As with TLS over TCP, QUIC encrypts packets with keys derived from the TLS
+handshake, using the AEAD algorithm negotiated by TLS.

Since TCP doesn't actually do the encryption, perhaps this would be more clearly stated as "As with the TLS record layer used with TCP, QUIC...."

>  
-For example, assuming a hash function with a 32 octet output, derivation for a
-client packet protection key would use HKDF-Expand with an `info` parameter of
-0x00200851554943206b6579.
+The keys for the Initial encryption level are computed based on
+the client's first Destination Connection Id, as described in

ID

>  
-Packets that carry the TLS handshake (Initial, Retry, and Handshake) are
-protected with a secret derived from the Destination Connection ID field from
-the client's Initial packet.  Specifically:
+Initial packets are protected with
+a secret derived from the Destination Connection ID field from the client's
+Initial packet.  Specifically:

First Initial packet, or does the key change with the DCID of each new Initial the client sends?

>  ~~~
 
 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 QHKDF-Expand
-is the connection ID chosen by the client.
+{{!SHA=DOI.10.6028/NIST.FIPS.180-4}}.  The connection ID used with
+HKDF-Expand-Label is the connection ID chosen by the client.

initial Destination Connection ID

> @@ -743,121 +653,11 @@ Note:
 
 : The Destination Connection ID is of arbitrary length, and it could be zero
   length if the server sends a Retry packet with a zero-length Source Connection
-  ID field.  In this case, the handshake keys provide no assurance to the client
+  ID field.  In this case, the initial keys provide no assurance to the client

Initial

> @@ -873,26 +673,20 @@ from the packet number.
 All QUIC packets other than Version Negotiation and Stateless Reset 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
-client's connection ID (see {{handshake-secrets}}).  This provides protection
+client's connection ID (see {{initial-secrets}}).  This provides protection

initial Destination Connection ID

>  
-### Retransmission and Acknowledgment of Unprotected Packets
+: 0-RTT data can be acknowledged by the server as it receives it, but any

Is this being formatted the way you want it?  It's being rendered as a definition of the previous line (MUST NOT use 0-RTT keys), which looks a little weird for prose.  It seems like it should just be a straight paragraph of text....

>  
-A HelloRetryRequest handshake message might be used to reject an initial
-ClientHello.  A HelloRetryRequest handshake message is sent in a Retry packet;
-any second ClientHello that is sent in response uses a Initial packet type.
-These packets are only protected with a predictable key (see
-{{handshake-secrets}}).  This is natural, because no shared secret will be
-available when these messages need to be sent.  Upon receipt of a
-HelloRetryRequest, a client SHOULD cease any transmission of 0-RTT data; 0-RTT
-data will only be discarded by any server that sends a HelloRetryRequest.
+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

MUST NOT (BUT WE KNOW YOU WILL).  6919 OUGHT TO have mentioned that one.

>  
-Once 1-RTT keys are available to an endpoint, it no longer needs the TLS
-handshake messages that are carried in unprotected packets.  However, a server
-might need to retransmit its TLS handshake messages in response to receiving an
-unprotected packet that contains ACK frames.  A server MUST process ACK frames
-in unprotected packets until the TLS handshake is reported as complete, or it
-receives an ACK frame in a protected packet that acknowledges all of its
-handshake messages.
+Receiving and verifying the TLS Finished message is critical in
+ensuring the integrity of the TLS handshake.  A server MUST NOT use
+1-RTT protected packets from the client prior to verifying the client
+Finished message if its response depends on client authentication.

But it provides an additional conditional that the previous one doesn't which is interest.  MUST NOT ... *if* its response depends on client authentication.  So we're willing to tolerate a tampered ClientHello for transferring public data, and just assume decryption will fail on the other side?

> -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.
-
-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.
-
-Receiving and verifying the TLS Finished message is critical in ensuring the
-integrity of the TLS handshake.  A server MUST NOT use protected packets from
-the client prior to verifying the client Finished message if its response
-depends on client authentication.
+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 be
+detected as soon as the TLS handshake completes.

"...will cause the TLS handshake to fail."?

> @@ -1592,6 +996,11 @@ 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 be detected
+when the handshake completes.

Same as previous.  Also, rewrap.

>  
 All these packets use the long header and contain the current QUIC version in
 the version field.
 
-In order to prevent tampering by version-unaware middleboxes, handshake packets
-are protected with a connection- and version-specific key, as described in
-{{QUIC-TLS}}. This protection does not provide confidentiality or integrity
-against on-path attackers, but provides some level of protection against
-off-path attackers.
+In order to prevent tampering by version-unaware middleboxes, Initial
+packets are protected with a connection- and version-specific keys

"with ~a~... keys"

>  
 
 ### Initial Packet {#packet-initial}
 
 The Initial packet uses long headers with a type value of 0x7F.  It carries the
-first cryptographic handshake message sent by the client.
+first CRYPTO_HS frames sent by the client as well as the
+cryptographic messages sent by the server to perform key exchange. The Initial
+packet is protected by Initial keys as described in {{QUIC-TLS}}.

Rewrap.

> +Token Length:
+
+: A variable-length integer specifying the length of the Token field, in bytes.
+It may be zero if no token is present. The server MUST send a zero-length
+token.
+
+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. This includes all cases where a new
+packet containing the initial cryptographic message needs to be created, this
+includes the packets sent after receiving a Version Negotiation
+({{packet-version}}) or Retry packet ({{packet-retry}}).

"This includes..., this includes...." is an awkward construction.  Perhaps "In addition to the first packet(s), this also includes all cases where a new packet containing the initial cryptographic message needs to be created, such as...."?

> +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. This includes all cases where a new
+packet containing the initial cryptographic message needs to be created, this
+includes 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 conveys a CRYPTO_HS frame (or frames)

conveys => includes

> +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. This includes all cases where a new
+packet containing the initial cryptographic message needs to be created, this
+includes 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 conveys a CRYPTO_HS frame (or frames)

Not necessarily; it could just include ACKs of handshake messages.

> +: 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. This includes all cases where a new
+packet containing the initial cryptographic message needs to be created, this
+includes 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 conveys a CRYPTO_HS frame (or frames)
+containing a cryptographic handshake message. The first CRYPTO_HS frame
+send always begins at an offset of 0 (see {{handshake}}). The client's complete

sent

> +The client and server use the Initial packet type for any packet that contains
+an initial cryptographic handshake message. This includes all cases where a new
+packet containing the initial cryptographic message needs to be created, this
+includes 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 conveys a CRYPTO_HS frame (or frames)
+containing a cryptographic handshake message. The first CRYPTO_HS frame
+send 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 starting immediately after the first one.

"starting immediately after" could be misconstrued as packet layout.  Perhaps "continuing the sequence of handshake messages"?

> +
+The payload of an Initial packet conveys a CRYPTO_HS frame (or frames)
+containing a cryptographic handshake message. The first CRYPTO_HS frame
+send 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 starting immediately after the first one.
+
+
+#### Connection IDs
+
+When an 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 a randomly selected value.  This MUST be at least 8 octets in length. Until
+a packet is received from the server, the client MUST use the same random value
+unless it also changes the Source Connection ID (which effectively starts a new

Is there a way in which this is just "effectively"?  Maybe "...unless it abandons the connection attempt and begins a new one.  In this case, the client MUST change the Source Connection ID."

> +containing a cryptographic handshake message. The first CRYPTO_HS frame
+send 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 starting immediately after the first one.
+
+
+#### Connection IDs
+
+When an 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 a randomly selected value.  This MUST be at least 8 octets in length. Until
+a packet is received from the server, the client MUST use the same random value
+unless it also changes the Source Connection ID (which effectively starts a new
+connection attempt).  The randomized Destination Connection ID is used to
+determine packet protection keys.

Initial

>  
 The client populates the Source Connection ID field with a value of its choosing
 and sets the SCIL field to match.
 
-The first Initial packet that is sent by a client contains a packet number of 0.
-All subsequent packets contain a packet number that is incremented by at least
-one, see ({{packet-numbers}}).
-
-The payload of an Initial packet conveys a STREAM frame (or frames) for stream
-0 containing a cryptographic handshake message.  The stream in this packet
-always starts at an offset of 0 (see {{stateless-retry}}) and the complete
-cryptographic handshake message MUST fit in a single packet (see {{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

Perhaps "the" connection ID?

>  
 The client populates the Source Connection ID field with a value of its choosing
 and sets the SCIL field to match.
 
-The first Initial packet that is sent by a client contains a packet number of 0.
-All subsequent packets contain a packet number that is incremented by at least
-one, see ({{packet-numbers}}).
-
-The payload of an Initial packet conveys a STREAM frame (or frames) for stream
-0 containing a cryptographic handshake message.  The stream in this packet
-always starts at an offset of 0 (see {{stateless-retry}}) and the complete
-cryptographic handshake message MUST fit in a single packet (see {{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

This implies the server can have multiple consistent SCIDs during the handshake.  "...MUST use a consistent SCID during the handshake."

> -
-The payload of an Initial packet conveys a STREAM frame (or frames) for stream
-0 containing a cryptographic handshake message.  The stream in this packet
-always starts at an offset of 0 (see {{stateless-retry}}) and the complete
-cryptographic handshake message MUST fit in a single packet (see {{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. The client MUST
+discard any subsequent packets it receives with different

"with a different SCID" probably, since the packet contains only one SCID.

> +
+#### Tokens
+
+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.
+
+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

Additionally, the token could have been issued by a previous iteration of the server with a different key / token generation scheme, as described in the following paragraph.  I can see an argument for this being SHOULD, however -- this isn't a case of becoming incompatible with other implementations, but a footgun.  If you don't do this, you'll break yourself if you don't retain the ability to parse your old tokens.

>  
-Continuing the cryptographic handshake is necessary to ensure that an attacker
-cannot force a downgrade of any cryptographic parameters.  In addition to
-continuing the cryptographic handshake, the client MUST remember the results of
-any version negotiation that occurred (see {{version-negotiation}}).  The client
-MAY also retain any observed RTT or congestion state that it has accumulated for
-the flow, but other transport state MUST be discarded.
+If the Original Destination Connection ID field does not match the
+Destination Connection ID from the Initial packet it sent, clients MUST
+discard the packet. This prevents an off-path attacker from injecting
+a Retry packet with a bogus new Source Connection ID.

"...from injecting a fabricated Retry packet."

>  
-If the server expects to generate more than three Handshake packets in response
-to an Initial packet, it SHOULD include a PATH_CHALLENGE frame in each Handshake
-packet that it sends.  After receiving at least one valid PATH_RESPONSE frame,
-the server can send its remaining Handshake packets. Servers can instead perform
-address validation using a Retry packet; this requires less state on the server,
-but could involve additional computational effort depending on implementation
-choices.
+Servers MUST NOT send more than three packets including Initial and Handshake

See #1458.  This should perhaps be three datagrams.

> @@ -694,7 +777,7 @@ Packets protected with 0-RTT keys use a type value of 0x7C.  The connection ID
 fields for a 0-RTT packet MUST match the values used in the Initial packet
 ({{packet-initial}}).
 
-The client can send 0-RTT packets after receiving a Handshake packet
+The client can send 0-RTT packets after receiving an Initial or Handshake packet

Handshake gets a back-reference; why doesn't Initial?

> -least one after sending a packet.
+maintains a separate packet number for sending and receiving.
+
+Packet numbers are divided into 3 spaces in QUIC:
+
+- Initial space: All Initial packets {{packet-initial}} are in this space.
+- Handshake space: All Handshake packets {{packet-handshake}} are in this space.
+- Application data space: All 0-RTT and 1-RTT encrypted packets
+  {{packet-protected}} are in this space.
+
+As descibed in {{QUIC-TLS}}, each packet type uses different encryption keys.
+
+Conceptually, a packet number space is the encryption context in which a packet
+can be processed and ACKed.  Initial packets can only be sent with
+Initial encryption keys and ACKed in packets which are also Initial packets.
+Similarly Handshake packets can only be sent and acked in Handshake packets.

"Similarly," and "ACKed" / "acked" => "acknowledged"

>  
 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.
 
-Details of how TLS is integrated with QUIC is provided in more detail in
-{{QUIC-TLS}}.
+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.
+
+## Example Handshake Flows
+
+Details of how TLS is integrated with QUIC are provided in {{QUIC-TLS}},
+but we provide some examples here.

Document typically avoids the first person.  "...but some examples are provided here."

>  connection state MUST use the Retry packet ({{packet-retry}}).  This packet
-causes a client to reset its transport state and to continue the connection
-attempt with new connection state while maintaining the state of the
-cryptographic handshake.
-
-A server MUST NOT send multiple Retry packets in response to a client handshake
-packet.  Thus, any cryptographic handshake message that is sent MUST fit within
-a single packet.
-
-In TLS, the Retry packet type is used to carry the HelloRetryRequest message.
+causes a client to restart the connection attempt and includes the token in the

"include~s~"

> @@ -1459,68 +1623,69 @@ To send additional data prior to completing the cryptographic handshake, the
 server then needs to validate that the client owns the address that it claims.
 
 Source address validation is therefore performed during the establishment of a
-connection.  TLS provides the tools that support the feature, but basic
-validation is performed by the core transport protocol.
+connection, by the core transport protocol.

"performed by the core transport protocol during the establishment of a connection."

>  
 A server MAY provide clients with an address validation token during one
 connection that can be used on a subsequent connection.  Address validation is
 especially important with 0-RTT because a server potentially sends a significant
 amount of data to a client in response to 0-RTT data.
 
-A different type of token is needed when resuming.  Unlike the token that is
-created during a handshake, there might be some time between when the token is
-created and when the token is subsequently used.  Thus, a resumption token
-SHOULD include an expiration time.  It is also unlikely that the client port
-number is the same on two different connections; validating the port is
+The server uses the NEW_TOKEN frame {{frame-new-token}} to provide the client
+with an address validation token that can be used to validate future 0-RTT
+connections.  The client may then use this token to validate future 0-RTT
+connections by including it in the Initial packet's header.  The client MUST
+NOT use the token provided in a RETRY for future connections.

Title case, not all-caps.

>  
 A server MAY provide clients with an address validation token during one
 connection that can be used on a subsequent connection.  Address validation is
 especially important with 0-RTT because a server potentially sends a significant
 amount of data to a client in response to 0-RTT data.
 
-A different type of token is needed when resuming.  Unlike the token that is
-created during a handshake, there might be some time between when the token is
-created and when the token is subsequently used.  Thus, a resumption token
-SHOULD include an expiration time.  It is also unlikely that the client port
-number is the same on two different connections; validating the port is
+The server uses the NEW_TOKEN frame {{frame-new-token}} to provide the client
+with an address validation token that can be used to validate future 0-RTT
+connections.  The client may then use this token to validate future 0-RTT
+connections by including it in the Initial packet's header.  The client MUST
+NOT use the token provided in a RETRY for future connections.
+
+Unlike the token that is created for a Retry packet, there might be some time
+between when the token is created and when the token is subsequently used.
+Thus, a resumption token SHOULD include an expiration time.  The server may

MAY?  Might?  Could?

> @@ -2929,6 +3070,34 @@ PATH_CHALLENGE frame previously sent by the endpoint, the endpoint MAY generate
 a connection error of type UNSOLICITED_PATH_RESPONSE.
 
 
+## NEW_TOKEN frame {#frame-new-token}
+
+An server sends a NEW_TOKEN frame (type=0x21) to provide the client a token to

"A~n~"

> +that each encryption level is treated as a separate CRYPTO_HS 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.
+
+
+## CRYPTO_CLOSE Frame {#frame-crypto-close}
+
+The CRYPTO_CLOSE frame (type=0x20) is used to indicate connection failures
+caused by the crypto handshake. It uses the same format as the
+CONNECTION_CLOSE frame ({{frame-connection-close}}), except that the
+error codes are specific to the crypto protocol in use. For TLS 1.3,
+the error code is simply the one-byte TLS alert number.

The error code in the other two frames is two bytes long.  Is this frame shorter (in which case the format is not the same), or is the MSB of the error code always zero?

> @@ -3064,6 +3293,10 @@ 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 ACKed or the crypto state

"acknowledged"

> @@ -3299,8 +3532,7 @@ The two type bits from a Stream ID therefore identify streams as summarized in
 | 0x3      | Server-Initiated, Unidirectional |
 {: #stream-id-types title="Stream ID Types"}
 
-Stream ID 0 (0x0) is a client-initiated, bidirectional stream that is used for
-the cryptographic handshake.  Stream 0 MUST NOT be used for application data.
+The first bi-directional stream opened by the client is stream 0.

For people who don't have the Stream 0 legacy (intended audience of this doc), is this statement even relevant?

> @@ -3893,6 +4102,14 @@ 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}
+
+Data sent in CRYPTO_HS 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
+is no excessive buffering at multiple layers.

no => not

> @@ -4313,6 +4531,15 @@ the range from 0xFE00 to 0xFFFF.
 
 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).
+- No more stream 0.

Stream 0 still exists.  Maybe "Stream 0 is no longer reserved for the cryptographic handshake.  Instead, CRYPTO_HS frames are used."

> -new packet with a new packet number, removing ambiguity about which packet is
-acknowledged when an ACK is received.  Consequently, more accurate RTT
-measurements can be made, spurious retransmissions are trivially detected, and
-mechanisms such as Fast Retransmit can be applied universally, based only on
-packet number.
+QUIC's packet number is strictly increasing within a packet number
+space, and directly encodes transmission order.  A higher QUIC packet
+number signifies that the packet was sent later, and a lower QUIC
+packet number signifies that the packet was sent earlier.  When a
+packet containing frames is deemed lost, QUIC rebundles the
+retransmittable data in a new packet with a new packet number,
+removing ambiguity about which packet is acknowledged when an ACK is
+received.  Consequently, more accurate RTT measurements can be made,
+spurious retransmissions are trivially detected, and mechanisms such
+as Fast Retransmit can be applied universally, based only on packet
+number.

The only change here seems to be that it was rewrapped to a smaller width than the rest of the document.  Is this necessary?

>  
-(TODO: Work this section some more. Add text on client vs. server, and on
-stateless retry.)
+A RETRY packet causes the content of the client's Initial packet to be

Packet types are title-cased, not all-caps.  Same on line 318.

>  
-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 default maximum ack delay in QUIC is 25ms.
+There are cases where one may be able to gain recovery information from
+acknowledgements of packets in another packet number space, but they rely
+on complex assumptions about the peer’s processing and acknowledgement
+algorithms.  Even those are unable to quickly recover from cases such as
+losing the client's Initial, but receiving the 0-RTT packets.  Below is
+an optimization using coalesced packets and implicit acknowledgements.

I don't see the optimization using coalesced packets and implicit acknowledgements.  If it's not immediately below this statement, perhaps add a forward reference?

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/1450#pullrequestreview-129681935