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

From: ekr <[email-masked]>
Date: Fri, 15 Jun 2018 15:39:42 +0000 (UTC)

@martinthomson 
You can view, comment on, or merge this pull request online at:

  https://github.com/quicwg/base-drafts/pull/1450

-- Commit Summary --

  * Output of Stream 0 Design Team.
  * Fix changelog
  * Fix whitespace
  * Offset and length fields in CRYPTO_HS are not optional
  * Remove EMPTY_ACK
  * Incorporate the comments from PR#1377
  * Remove EMPTY_ACK
  * Update draft-ietf-quic-transport.md
  * Add the TLS diagrams
  * Redact diagram from the TLS doc
  * Ian Swett's comments
  * server-initiated streams start from 1
  * Remove last TODO
  * Minor editorial
  * Remove the advice on how to use coalesced packets for recovery.
  * Self-review, ready to submit
  * Some more cleanup

-- File Changes --

    M draft-ietf-quic-recovery.md (146)
    M draft-ietf-quic-tls.md (1384)
    M draft-ietf-quic-transport.md (793)

-- Patch Links --

https://github.com/quicwg/base-drafts/pull/1450.patch
https://github.com/quicwg/base-drafts/pull/1450.diff

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

---

From: Christopher Wood <[email-masked]>
Date: Fri, 15 Jun 2018 08:41:31 -0700

chris-wood commented on this pull request.

> @@ -107,7 +111,7 @@ important to the loss detection and congestion control machinery below.
 * Retransmittable packets are those that contain at least one
   retransmittable frame.
 
-* Crypto handshake data is sent on stream 0, and uses the reliability
+* Crypto handshake data is sent in CRYPTO_HS frames, and uses the reliability

👍 

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

---

From: ekr <[email-masked]>
Date: Fri, 15 Jun 2018 15:47:23 +0000 (UTC)

@ekr pushed 1 commit.

777114a  Fix compile errors

-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/quicwg/base-drafts/pull/1450/files/396c318dabd73952ee44b4bf1826aa28ebd19d8b..777114ac355c7a4b15dabd67122ca21c164e2e17

---

From: Nick Banks <[email-masked]>
Date: Fri, 15 Jun 2018 10:13:45 -0700

nibanks commented on this pull request.

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

Would it be reasonable to allow the BLOCKED frames in 0-RTT, assuming the previous connection set very small limits in it's TP? For instance, what if the previous connection set the initial maximum number of bidirectional streams to 1, and the client would like to open 2 streams in 0-RTT. Should it be allowed to open 1 stream and include a `STREAM_ID_BLOCKED` frame?

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

---

From: Nick Banks <[email-masked]>
Date: Fri, 15 Jun 2018 11:06:21 -0700

Some small comments.

>  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

`the` is included twice here.

> @@ -1608,14 +1017,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.
 
-Certificate caching {{?RFC7924}} can reduce the size of the server's handshake
-messages significantly.
-
-QUIC requires that the packet containing a ClientHello be padded to a minimum
-size.  A server is less likely to generate a packet reflection attack if the
-data it sends is a small multiple of this size.  A server SHOULD use a
-HelloRetryRequest if the size of the handshake messages it sends is likely to
-significantly exceed the size of the packet containing the ClientHello.
+QUIC includes three defenses against this attack. First, the packet
+containing a ClientHello be padded to a minimum size. Second, if
+responding to an unverified source address, the server is forbidden to
+send more than three packets in its first flight ({{QUIC-TRANSPORT}};
+Section 4.4.3). Finally, because ACKs of Handshake packets
+are authenticated, a blind attacker cannot forge them

Missing a `.` after "forge them".

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

I feel this `SHOULD` needs to be a `MUST`. If QUIC is support independent DDoS protection devices in path, then the QUIC server cannot drop Initial packets with tokens it doesn't understand.

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

---

From: Kazuho Oku <[email-masked]>
Date: Mon, 18 Jun 2018 00:00:52 -0700

kazuho commented on this pull request.

+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 "tls 13". The purpose of this change is to provide key

`"tls 13"` should be `"tls13 "` (notice the position of the whitespace)

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

---

From: Kazuho Oku <[email-masked]>
Date: Mon, 18 Jun 2018 00:34:22 -0700

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

This paragraph seems redundant. The PR already has the following text starting from line 843,
```
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}}).
```

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

---

From: ianswett <[email-masked]>
Date: Mon, 18 Jun 2018 13:24:56 -0700

@ianswett pushed 1 commit.

a4ad49b  Restore Generating Acknowledgements

-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/quicwg/base-drafts/pull/1450/files/777114ac355c7a4b15dabd67122ca21c164e2e17..a4ad49b42d9c6e7f86b1127cc4291f70d5fbe835

---

From: Mike Bishop <[email-masked]>
Date: Mon, 18 Jun 2018 15:52:57 -0700

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?

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.)

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

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
+

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

---

From: ekr <[email-masked]>
Date: Mon, 18 Jun 2018 17:02:57 -0700

ekr commented on this pull request.

Oh, I meant to delete this graf too

We also have CRYPTO_CLOSE. It's also confusing to have HANDSHAKE frames in !Handshake packets.

I would really prefer not to change this at this time. I'm happy to bikeshed this later, but it's going to be much easier to s/CRYPTO_HS/<whatever>/ than any of the more generic alternatives, and so this doesn't need to block the PR.

I am going to leave this up to MT's discretion.

You should open an issue for BLOCKED.

Yes, this just got missed in my edit. I can fix.

-~~~
-struct {

I think this is fine as-is. The TLS record layer is never used alone with TCP. But I'll leave it to MT's discretion.

Yes, that's correctl

OK

-- 
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#discussion_r196259663

---

From: Mike Bishop <[email-masked]>
Date: Mon, 18 Jun 2018 18:01:43 -0700

Okay, then this one doesn't apply. 

-- 
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#discussion_r196268757

---

From: ianswett <[email-masked]>
Date: Tue, 19 Jun 2018 05:54:46 -0700

ianswett commented on this pull request.

I moved Crypto Handshake Data below under generating acknowledgements.

-- 
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#discussion_r196410869

---

From: ekr <[email-masked]>
Date: Tue, 19 Jun 2018 12:57:27 +0000 (UTC)

@ekr pushed 2 commits.

6b36300  Mike's comments
0cfdf67  Merge pull request #34 from ekr/ianswett-mike-comments

-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/quicwg/base-drafts/pull/1450/files/a4ad49b42d9c6e7f86b1127cc4291f70d5fbe835..0cfdf67b77f7f52a0fd3cec28064f4c87d9cde7d

---

From: ekr <[email-masked]>
Date: Tue, 19 Jun 2018 13:09:34 +0000 (UTC)

@ekr pushed 2 commits.

4065266  Fix retry and remove optimizations
954c585  Merge pull request #35 from ekr/ianswett-mike2

-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/quicwg/base-drafts/pull/1450/files/0cfdf67b77f7f52a0fd3cec28064f4c87d9cde7d..954c585e680ca4bf8e2e18af57e5832b716d9fb7

---

From: Rui Paulo <[email-masked]>
Date: Tue, 19 Jun 2018 16:07:50 -0700

rpaulo commented on this pull request.

I'm not sure where to point this out, but shouldn't we have a restriction saying that a QUIC packet can only have *one* CRYPTO_HS frame?

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

---

From: Rui Paulo <[email-masked]>
Date: Tue, 19 Jun 2018 16:13:08 -0700

+- 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.
+
+Because packets may 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.

I think that, up to this point, we were relying on the fact that typical UDP stacks give us a clear per-packet boundary and this changes that.  Do we now see implementations receiving a UDP packet and assuming it might contain more than one QUIC packet?
It seems like the only way to implement this is to start parsing the QUIC packet and then, if there are leftover bytes, interpret that as another QUIC packet.
It's not too hard but it seems like a significant change.

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

---

From: ekr <[email-masked]>
Date: Tue, 19 Jun 2018 16:28:38 -0700

Why? That's not, for instance, how Minq works.

-- 
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#discussion_r196609514

---

From: Rui Paulo <[email-masked]>
Date: Tue, 19 Jun 2018 16:29:38 -0700

-The HKDF-Expand function used by QHKDF-Expand uses the PRF hash function
-negotiated by TLS, except for handshake secrets and keys derived from them (see
-{{handshake-secrets}}).
+If TLS experiences an error, it MUST generate an appropriate alert
+as defined in {{TLS13}}; Section 6) and then provide it to QUIC,
+which sends the alert in a CRYPTO_CLOSE frame. All such alerts are
+"fatal".

"fatal" is under quotes but its meaning isn't explained.

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

---

From: ekr <[email-masked]>
Date: Tue, 19 Jun 2018 16:29:53 -0700

That's already documented under coalesced packets, I think: https://tools.ietf.org/html/draft-ietf-quic-transport-12#section-4.6

-- 
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#discussion_r196609791

---

From: Rui Paulo <[email-masked]>
Date: Tue, 19 Jun 2018 16:32:38 -0700

>  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
 input.
 
-Once TLS has provided a key, the contents of regular QUIC packets immediately
-after any TLS messages have been sent are protected by the AEAD selected by TLS.
-
-The key, K, is either the client packet protection key (client_pp_key\<i>) or
-the server packet protection key (server_pp_key\<i>), derived as defined in
-{{key-expansion}}.
-
-The nonce, N, is formed by combining the packet protection IV (either
-client_pp_iv\<i\> or server_pp_iv\<i\>) with the packet number.  The 64 bits
-of the reconstructed QUIC packet number in network byte order is left-padded
-with zeros to the size of the IV.  The exclusive OR of the padded packet number
-and the IV forms the AEAD nonce.
+The key and iv for the packet are computed as described in {{encryption-keys}}.

IV

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

---

From: Rui Paulo <[email-masked]>
Date: Tue, 19 Jun 2018 16:33:13 -0700

-after any TLS messages have been sent are protected by the AEAD selected by TLS.
-
-The key, K, is either the client packet protection key (client_pp_key\<i>) or
-the server packet protection key (server_pp_key\<i>), derived as defined in
-{{key-expansion}}.
-
-The nonce, N, is formed by combining the packet protection IV (either
-client_pp_iv\<i\> or server_pp_iv\<i\>) with the packet number.  The 64 bits
-of the reconstructed QUIC packet number in network byte order is left-padded
-with zeros to the size of the IV.  The exclusive OR of the padded packet number
-and the IV forms the AEAD nonce.
+The key and iv for the packet are computed as described in {{encryption-keys}}.
+The nonce, N, is formed by combining the packet protection IV with the
+packet number.  The 64 bits of the reconstructed QUIC packet number in
+network byte order is left-padded with zeros to the size of the IV.

"is left-padded" or "are left-padded"?

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

---

From: Rui Paulo <[email-masked]>
Date: Tue, 19 Jun 2018 16:45:31 -0700

Because it's like having two STREAM frames for the same stream ID.

-- 
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#discussion_r196612421

---

From: Rui Paulo <[email-masked]>
Date: Tue, 19 Jun 2018 16:47:00 -0700

OK, got it.

-- 
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#discussion_r196612668

---

From: Rui Paulo <[email-masked]>
Date: Tue, 19 Jun 2018 16:50:05 -0700

typo? is padded to?

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

---

From: ekr <[email-masked]>
Date: Tue, 19 Jun 2018 16:50:24 -0700

This also seems to be permitted for STREAM frames:

```
   Stream multiplexing is achieved by interleaving STREAM frames from
   multiple streams into one or more QUIC packets.  A single QUIC packet
   can include multiple STREAM frames from one or more streams.
```

-- 
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#discussion_r196613186

---

From: Mike Bishop <[email-masked]>
Date: Tue, 19 Jun 2018 16:58:11 -0700

There's nothing wrong with having multiple STREAM frames from the same stream, and I don't see anything wrong with having multiple CRYPTO_HS frames for the same reason.  Presumably, they contain different regions of the handshake stream generated at different points by the TLS stack.

(If they claim to contain the same region of data but differ, that might be a good reason to blow up, of course....)

-- 
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#discussion_r196614410

---

From: Rui Paulo <[email-masked]>
Date: Tue, 19 Jun 2018 17:13:24 -0700

Right, so I get the case where more than one CRYPTO_HS/STREAM frame is present but at least we should mention what to do if they overlap.

-- 
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#discussion_r196616553

---

From: ekr <[email-masked]>
Date: Tue, 19 Jun 2018 17:50:58 -0700

I think we should, but not limit it to the case where they are in the same packet. The situation is the same if they are in two different packets.

-- 
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#discussion_r196621214

---

From: Rui Paulo <[email-masked]>
Date: Tue, 19 Jun 2018 19:17:24 -0700

If they are in two different packets then it's just a retransmission ;-)
I'm thinking we just need some text saying the receive is supposed to detect and handle overlapping CRYPTO_HS/STREAM frame even if they are in the same packet.  Maybe we already have that, but I don't see it.

-- 
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#discussion_r196631210

---

From: ekr <[email-masked]>
Date: Tue, 19 Jun 2018 19:58:21 -0700

Sure. Given that CRYPTO_HS has the same semantics in this respect as STREAM, I suggest a separate PR that adds it to the stream section.

-- 
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#discussion_r196635694

---

From: Martin Thomson <[email-masked]>
Date: Tue, 19 Jun 2018 22:12:25 -0700

martinthomson approved this pull request.

At risk of this turning into a unicorn, here are my comments.  I don't think that you need to address all of them, but I would appreciate you taking one pass through this so we don't have too many editorial landmines to worry about later.  Most are nitty, so they should be easy to fix; others I'm happy to punt on.

On the renaming of frames and the removal of CRYPTO_CLOSE, I think that we can easily make that sort of change later.  And I plan to do so.

An appeal to those commenting on this PR.  This is almost at the point that GitHub is going to choke on it, if it doesn't start doing that already.  If you have nits, questions, or responses to others comments, please refrain from adding to the pile of comments.  If you think that there is a substantive issue that this PR creates, please open an issue.

s/CRYPTO_HS/CRYPTO/g

Yes, I understand that there is a message that carries a TLS alert, but I don't think that's ideal.  If we want to carry alerts, we can pack the range of cryptographic alerts into the CONNECTION_CLOSE space, or recommend that the reason phrase start with the alert.

> @@ -120,6 +124,17 @@ algorithms here that parallel well-known TCP ones. Protocol differences between
 QUIC and TCP however contribute to algorithmic differences. We briefly describe
 these protocol differences below.
 
+### Separate Packet Number Spaces
+
+QUIC uses separate packet number spaces for each encryption level, except that
+0-RTT and all generations of 1-RTT keys use the same packet number space.
+Separating the spaces allows the recovery mechanisms to work without special
+cases to avoid spuriously retransmitting un-processable packets.

This really doesn't say why.  I think that you want to say that separating the spaces ensures that packets from different spaces, which can't be decrypted, could trigger spurious retransmission.

> @@ -120,6 +124,17 @@ algorithms here that parallel well-known TCP ones. Protocol differences between
 QUIC and TCP however contribute to algorithmic differences. We briefly describe
 these protocol differences below.
 
+### Separate Packet Number Spaces
+
+QUIC uses separate packet number spaces for each encryption level, except that
+0-RTT and all generations of 1-RTT keys use the same packet number space.
+Separating the spaces allows the recovery mechanisms to work without special
+cases to avoid spuriously retransmitting un-processable packets.
+Separate packet number spaces do not imply separate paths. Consequently,

I don't think that you need to talk about separate paths. It opens more questions than it answers.

-Handshake packets, which contain STREAM frames for stream 0, are critical to
-QUIC transport and crypto negotiation, so a separate alarm is used for them.
+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.

This h/H thing is not ideal, but we don't need to fix it before landing this.

-When the alarm fires, the sender MUST retransmit all unacknowledged handshake
-data, by calling RetransmitAllUnackedHandshakeData(). On each consecutive
-firing of the handshake alarm, the sender SHOULD double the handshake timeout
-and set an alarm for this period.
+When the alarm fires, the sender MUST retransmit all unacknowledged CRYPTO_HS

This needs to be in the same paragraph as the previous.

> @@ -422,6 +439,14 @@ 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

SHOULD?  and (later) MAY?

is it "ack delay" or "ACK delay"?

don't abbreviate crypto (that means cryptocurrency, dinchano?)

> @@ -559,6 +584,8 @@ sent_packets:
   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

ACK

> @@ -422,6 +439,14 @@ 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.
+

The full implications of the change to multiple packet number spaces doesn't seem to be present here.  Shouldn't this say something about RTO as well?  If I understand the design, packets sent with handshake and initial keys are retransmitted on this timer only, not RTO.

The awkward thing here is that this seems to lead to EndOfEarlyData being retransmitted on RTO, not the handshake timer.  We need an issue for chasing that down.

not MUST, can

The list here is accurate, but we can consider rotating it later.

+

s/may/could/

+
+Because packets may 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 |
+|:----------------|:-----------------|
+| Initial         | Initial secrets  |
+| 0-RTT Protected | 0-RTT            |
+| Handshake       | Handshake        |
+| Retry           | N/A              |
+| Short Header    | 1-RTT            |
+{: #packet-types-levels title="Encryption Levels by Packet Type"}

Any sense extending this to include packet number spaces?

+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 |
+|:----------------|:-----------------|
+| Initial         | Initial secrets  |
+| 0-RTT Protected | 0-RTT            |
+| Handshake       | Handshake        |
+| Retry           | N/A              |
+| Short Header    | 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 `[...]`, or use a comma

> -A QUIC server starts the process by providing TLS with stream 0 octets.
-
-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.
-
-At the server, when TLS provides handshake octets, it also needs to indicate
-whether the octets contain a HelloRetryRequest.  A HelloRetryRequest MUST always
-be sent in a Retry packet, so the QUIC server needs to know whether the octets
-are a HelloRetryRequest.
+A QUIC server starts the process by providing TLS with the client's
+handshake octets.
+
+At any given time, an endpoint will have a current sending encryption
+level and receiving encryption level. Each encryption level is

I don't think that we need this sentence any more.  If you consider that TLS provides octets that are explicitly destined for a particular epoch and that each epoch is clearly identified by the type of packet, then you only need to concern yourself with routing to the correct epoch.  This doesn't have to follow the strict linear regime that TLS assumes, which in any case is detrimental when you consider the potential for reordering.

It's fine to mention that later epochs might not be available early on and then (separately) saying that epochs can be discarded when they aren't needed.

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

I don't think that this works.  Consider EndOfEarlyData, which could be lost, then later repaired.  The end of the previously installed encryption level (aside from being only loosely defined) for CRYPTO is 0, so EOED would extend past that.  Also, if you take a looser interpretation, then a delayed 0-RTT STREAM frame might also extend that stream beyond the point where the server cut over to reading Handshake or 1-RTT.

> @@ -440,102 +433,63 @@ Important:
   STREAM frame that carries the Finished message in multiple packets.  This
   enables immediate server processing for those packets.
 
+### Encryption Level Changes

As above, rather than casting these as changes, it might be better to concentrate on availability of keys and how TLS targets particular keys.

For most frames, the notion of current level doesn't matter: you send in the latest 1-RTT if you can, 0-RTT if you can't otherwise, and don't send at all otherwise.

>                                                     Get Handshake
-                                                1-RTT Keys Ready
-                     <--- send/receive ---
+                      <------------ Initial
+                                          Rekey rx to 0-RTT keys

Consistent with the above, I don't think that we need to "rekey" reception, but rather install those keys and make them available.

The same applies to rekeying for transmission really.

This diagram is somewhat useful, but we should have text that it is only indicative, and that keys are selected based on the type of content being sent, or based on the type of packet that was received.

-QUIC uses a system of packet protection secrets, keys and IVs that are modelled
-on the system used in TLS {{!TLS13}}.  The secrets that QUIC uses
-as the basis of its key schedule are obtained using TLS exporters (see Section
-7.5 of {{!TLS13}}).
+A client that attempts 0-RTT MUST also consider 0-RTT to be rejected if it
+receives a Version Negotiation packet.

... or Retry.

-~~~
-struct {

Seems fine to me.

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

Section 7.3 of

+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 "tls 13". 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.

I don't think that we need this separation.  Isn't the fact that this is a QUIC connection separation enough?  The same TLS connection can't be used to key TLS record protection on a TCP connection.

If this remains, then we need to ensure that this is only ever the final derivation (those with "key" and "iv").  Otherwise, there might be confusion about the label provided to Derive-Secret as well.

Well, not entirely.  If the client changes the destination connection ID in response to Retry, then the packets will be protected with keys derived from that value.  Where this gets hairy is the Initial packets that the client needs to send after the server sends ServerHello or HelloRetryRequest, the first of which can change the destination connection ID.

ACK frames in Initial packets will probably then need to use the updated connection ID, and keys derived from the first Initial packet sent.  That's fine.  But if this is another ClientHello and we require the same rules, then we're preventing the use of a stateless HelloRetryRequest.

or "from the destination connection ID in the client's first Initial packet (see ..."

> @@ -1024,144 +795,90 @@ 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 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.

Unfortunately this doesn't work with 0-RTT, because we need reliable transmission of EndOfEarlyData.  That probably just needs a carve-out.

-A server might choose to retain 0-RTT packets that arrive before a TLS
-ClientHello.  The server can then use those packets once the ClientHello
-arrives.  However, the potential for denial of service from buffering 0-RTT
-packets is significant.  These packets cannot be authenticated and so might be
-employed by an attacker to exhaust server resources.  Limiting the number of
-packets that are saved might be necessary.
+A client MUST only use 0-RTT keys to protect data that is idempotent.  A client
+MAY wish to apply additional restrictions on what data it sends prior to the
+completion of the TLS handshake.  A client otherwise treats 0-RTT keys as
+equivalent to 1-RTT keys, except that ACKs for that data MUST only be sent with
+1-RTT keys.

"A server uses 1-RTT keys to protect acknowledgements of 0-RTT packets."

Either that or make it a note.

It's a shame we can't just use Handshake keys for those acknowledgments, but that would require a change in the design.

Let's drop this one.  No point in getting into the client authentication thing.

-## 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, for instance because of limits on AEAD
+encryption.  The KEY_PHASE bit in the short header is used to indicate

This "for instance" is a little stilted.  I don't have a good suggestion right now though.

We concluded that this wasn't packets, but UDP datagrams.

s/ACKs/acknowledgments/  (to allow for ACK_ECN)

 

Any sense mentioning acknowledgments here?

-If the client received a Retry packet and is sending a second Initial packet,
-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.
+~~~
+ 0                   1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|        Token Length (i)  ...

Check alignment.

> -results in a change to the keys used to protect the Initial packet.
+~~~
+ 0                   1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|        Token Length (i)  ...
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                            Token (*)                        ...
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+~~~
+
+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.

Initial packets sent by the server MUST include a zero-length token.

> +|        Token Length (i)  ...
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                            Token (*)                        ...
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+~~~
+
+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.

Is the client required to include a token on every Initial packet that it sends, including ones that include only ACK frames, or is it only the first and any that are sent in response to Retry?

Interestingly, if you take the first+Retry rule, then that matches neatly with the rules about which destination connection ID is used to determine keys.

an an

We've agreed to "unpredictable" in other such cases rather than "randomly".

This consistency requirement seems to be under debate.  We're currently gravitating toward a requirement to change the value on (almost) every Retry, and then allowing the first Initial packet from the server to set a new value.  Only after that can it be consistent.

Perhaps: "Once a client has received an Initial packet from the server, it MUST discard any packet it receives with a different Source Connection ID."

+Source Connection IDs.

This paragraph doesn't belong here really.  It's part of the description of Retry.

+#### Tokens
+

We can't assume retention of keys, but we can provide some recommendations.  If tokens are clearly marked as NEW_TOKEN vs. Retry, then the former might be old and broken, so treating that as equivalent to an absent token is reasonable.  For the latter, Retry might be verifiable.  If something is clearly a Retry token, then dropping the connection seems OK.

Needs more text.

+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}}).
+
+Note: The rationale for treating the client as unvalidated rather

Formatting for notes is generally to use a definition list:

```
Note:
: The rationale ...
```

> +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 message,
+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.
+
+#### Starting Packet Numbers
+
+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}}).

Do you start at zero again if you change the connection ID?  I don't think you do, but it might help to be clear on this point.

 ### Retry Packet {#packet-retry}
 
-A Retry packet uses long headers with a type value of 0x7E.  It carries
-cryptographic handshake messages and acknowledgments.  It is used by a server
-that wishes to perform a stateless retry (see {{stateless-retry}}).
+A Retry packet uses long headers with a type value of 0x7E. It carries an
+address validation token created by the server. It is used by a server that
+wishes to perform a stateless retry (see {{stateless-retry}}).
+
+~~~
+ 0                   1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|     DCIL(8)   |      Original Destination Connection ID (*)   |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                        Retry Token (*)

...

 ### Retry Packet {#packet-retry}
 
-A Retry packet uses long headers with a type value of 0x7E.  It carries
-cryptographic handshake messages and acknowledgments.  It is used by a server
-that wishes to perform a stateless retry (see {{stateless-retry}}).
+A Retry packet uses long headers with a type value of 0x7E. It carries an
+address validation token created by the server. It is used by a server that
+wishes to perform a stateless retry (see {{stateless-retry}}).
+
+~~~
+ 0                   1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|     DCIL(8)   |      Original Destination Connection ID (*)   |

ODCIL ?

"most recent Initial packet" (this will also help with the other problem we have)

-After receiving a Retry packet, the client uses a new
-Initial packet containing the next cryptographic handshake message.  The client
-retains the state of its cryptographic handshake, but discards all transport
-state.  The Initial packet that is generated in response to a Retry packet
-includes STREAM frames on stream 0 that start again at an offset of 0.
+A server MUST only send a Retry in response to a client Initial packet.

Do we need to include a minimum size constraint here as well?  A Retry that is sent in response to an ACK frame is just weird.

-The payload of the Retry packet contains at least two frames. It MUST include a
-STREAM frame on stream 0 with offset 0 containing the server's cryptographic
-stateless retry material. It MUST also include an ACK frame to acknowledge the
-client's Initial packet. It MAY additionally include PADDING frames. The next
-STREAM frame sent by the server will also start at stream offset 0.
+Otherwise, the client SHOULD respond with a new Initial
+packet with the Token field set to the token received in the Retry packet.

Following the above thought, I think that we need to prohibit this reaction from clients if they have received an Initial packet from the server.

> @@ -761,7 +844,7 @@ During the handshake, an endpoint might receive multiple packets with the long
 header, and thus be given multiple opportunities to update the Destination
 Connection ID it sends.  A client MUST only change the value it sends in the
 Destination Connection ID in response to the first packet of each type it
-receives from the server (Retry or Handshake); a server MUST set its value based
+receives from the server (Retry or Initial); a server MUST set its value based
 on the Initial packet.  Any additional changes are not permitted; if subsequent

We need more text here, but I think that we can instead say "in response to a Retry packet or the first Initial packet if receives from the server".

> @@ -792,15 +875,36 @@ response to connection migration ({{migration}}). NEW_CONNECTION_ID frames
 
 The packet number is an integer in the range 0 to 2^62-1. The value is used in
 determining the cryptographic nonce for packet encryption.  Each endpoint
-maintains a separate packet number for sending and receiving.  The packet number
-for sending MUST start at zero for the first packet sent and MUST increase by at
-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.

typo: described

-A QUIC endpoint MUST NOT reuse a packet number within the same connection (that
-is, under the same cryptographic keys).  If the packet number for sending
-reaches 2^62 - 1, the sender MUST close the connection without sending a
-CONNECTION_CLOSE frame or any further packets; an endpoint MAY send a Stateless
-Reset ({{stateless-reset}}) in response to further packets that it receives.
+This enforces cryptographic separation between the data sent in the
+different packet sequence number spaces.  As a result, each packet number space

s/As a result, //

> @@ -1084,14 +1191,16 @@ 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 0 for 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
+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

{{}}

>  cryptographic handshake protocol is in use.
 
-QUIC provides this stream with reliable, ordered delivery of data.  In return,
-the cryptographic handshake provides QUIC with:
+QUIC provides the cryptographic handshake with reliable, ordered
+delivery of data via the CRYPTO_HS frame.  In return, the

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.

> @@ -1118,19 +1227,83 @@ the cryptographic handshake provides QUIC with:
   client can receive packets that are addressed with the transport address that
   is claimed by the client (see {{address-validation}})
 
-The initial cryptographic handshake message 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.  Reassembling messages requires that a server maintain state
-prior to establishing a connection, exposing the server to a denial of service
-risk.
+The CRYPTO_HS frame provides an offset and a length.  QUIC functions
+as the record encryption layer for the cryptographic protocol.

With the above suggestion, drop this 'graph.

> @@ -1118,19 +1227,83 @@ the cryptographic handshake provides QUIC with:
   client can receive packets that are addressed with the transport address that
   is claimed by the client (see {{address-validation}})
 
-The initial cryptographic handshake message 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.  Reassembling messages requires that a server maintain state
-prior to establishing a connection, exposing the server to a denial of service
-risk.
+The CRYPTO_HS frame provides an offset and a length.  QUIC functions
+as the record encryption layer for the cryptographic protocol.
+
+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.

This duplicates the text from the next paragraph, partly.  Maybe combine them.

No need to mention CRYPTO_HS here though.

This best goes with the description of the CRYPTO_HS frame.

+## Example Handshake Flows
+
+Details of how TLS is integrated with QUIC are provided in {{QUIC-TLS}},
+but we provide some examples 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.
+
+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 anywhere
+from 4 to 9 UDP datagrams.  For instance, the server's first flight

Many more than 9 in the perverse case.  Just say "as few as 4 UDP datagrams, or any number more".

> +to increment from its 0-RTT packets.
+
+~~~~
+Client                                                  Server
+
+Initial[0]: CRYPTO_HS[CH]
+0-RTT[0]: STREAM[0, "..."] ->
+
+                              Initial[0]: CRYPTO_HS[SH] ACK[0]
+                     Handshake[0] CRYPTO_HS[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]
+1-RTT[2]: STREAM[0, "..."], ACK[0] ->

Commas here separate frames, but you didn't use them elsewhere.

> +to increment from its 0-RTT packets.
+
+~~~~
+Client                                                  Server
+
+Initial[0]: CRYPTO_HS[CH]
+0-RTT[0]: STREAM[0, "..."] ->
+
+                              Initial[0]: CRYPTO_HS[SH] ACK[0]
+                     Handshake[0] CRYPTO_HS[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]
+1-RTT[2]: STREAM[0, "..."], ACK[0] ->

This needs to show the entire handshake, even if that means duplicating a few things.  The important things missing are ACKs for 0-RTT[1] and Handshake[0] from the client.

> -port), a timestamp, and any other supplementary information the server will need
-to validate the token in the future.
-
-The cryptographic handshake is responsible for enacting validation by sending
-the address validation token to the client.  A legitimate client will include a
-copy of the token when it attempts to continue the handshake.  The cryptographic
-handshake extracts the token then asks QUIC a second time whether the token is
-acceptable.  In response, QUIC can either abort the connection or permit it to
-proceed.
+QUIC uses token-based address validation.  Any time the server wishes
+to validate a client address, it provides the client with a token.  As
+long as the token's authenticity can be checked (see
+{{token-integrity}}) and the client is able to return that token, it
+proves to the server that it received the token.
+
+If QUIC decides to request address validation for the current

"During the handshake, a server can request address validation by sending a Retry packet.  The token included in the Retry are consumed by the[...]"

> +long as the token's authenticity can be checked (see
+{{token-integrity}}) and the client is able to return that token, it
+proves to the server that it received the token.
+
+If QUIC decides to request address validation for the current
+handshake, it encodes the token in a Retry packet. The contents of
+this token are consumed by the server that generates the token, so
+there is no need for a single well-defined format.  A token could
+include information about the claimed client address (IP and port), a
+timestamp, and any other supplementary information the server will
+need to validate the token in the future.
+
+The Retry packet is sent to the client and a legitimate client will
+respond with an Initial packet containing the token from the Retry packet
+when it continues the handshake.  In response to receiving the token, a
+QUIC server can either abort the connection or permit it to proceed.

No need to qualify server here.  I don't know why we had so much "QUIC" in the old text.

 A connection MAY be accepted without address validation - or with only limited
 validation - but a server SHOULD limit the data it sends toward an unvalidated
 address.  Successful completion of the cryptographic handshake implicitly
 provides proof that the client has received packets from the server.
 
+The client should allow for additional Retry packets being sent in
+response to Initial packets sent containing a token. There are several
+situations in which the server might not be able to use the previously
+generated token to validate the client's address and must send a new
+Retry. A reasonable limit to the number of tries the client allows
+for, before giving up, is 3. That is, the client SHOULD echo the
+address validation token from a new Retry packet up to 3 times. After
+that, it MAY give up on the connection attempt.

I think that the SHOULD needs to be a MUST.  That is, clients need to have a minimum number of times they will pull on the thread before giving up.  No issue if they keep on pulling indefinitely, but servers need to be able to rely on a certain number of retries working.

drop "0-RTT" here.  Of course this is most useful for 0-RTT, but the token might also be used by servers with massive certificates or very large 0.5 RTT flights in the same way.

> @@ -2676,6 +2832,12 @@ QUIC acknowledgements are irrevocable.  Once acknowledged, a packet remains
 acknowledged, even if it does not appear in a future ACK frame.  This is unlike
 TCP SACKs ({{?RFC2018}}).
 
+It is expected that a sender will reuse the same packet number across different
+packet number spaces.  ACK frames only acknowledge the packet numbers that were
+transmitted by the sender in the same packet number space of the packet that the
+ACK was received in.  This is an important property to allow for separation
+between the different packet number spaces.

Delete the last sentence.  There's no alternative to this design so this needs no further justification.

> @@ -2839,6 +3001,9 @@ is only sending ACK frames will only receive acknowledgements for its packets
 if the sender includes them in packets with non-ACK frames.  A sender SHOULD
 bundle ACK frames with other frames when possible.
 
+Implementations must be aware of the packet number space of the packet being
+transmitted and only acknowledge packets from that space.

This is an odd statement.  How about: "Endpoints can only acknowledge packets sent in a particular packet number space by sending ACK frames in packets from the same packet number space."

> @@ -2849,43 +3014,19 @@ received packets in preference to packets received in the past.
 
 ### ACK Frames and Packet Protection
 
-ACK frames that acknowledge protected packets MUST be carried in a packet that
-has an equivalent or greater level of packet protection.
-
-Packets that are protected with 1-RTT keys MUST be acknowledged in packets that
-are also protected with 1-RTT keys.
-
-A packet that is not protected and claims to acknowledge a packet number that
-was sent with packet protection is not valid.  An unprotected packet that
-carries acknowledgments for protected packets MUST be discarded in its entirety.
+ACK frames MUST only be carried in a packet that has the same packet

The MUST isn't useful here.  It's not an interoperability requirement, because there is no alternative.

"ACK frames only acknowledge packets from the same packet number space as the packet that carries them.  For instance, ...."

> -messages in the next unprotected packet that it sends, unless it is able to
-acknowledge those packets in later packets protected by 1-RTT keys.  At the
-completion of the cryptographic handshake, both peers send unprotected packets
-containing cryptographic handshake messages followed by packets protected by
-1-RTT keys. An endpoint SHOULD acknowledge the unprotected packets that complete
-the cryptographic handshake in a protected packet, because its peer is
-guaranteed to have access to 1-RTT packet protection keys.
-
-For instance, a server acknowledges a TLS ClientHello in the packet that carries
-the TLS ServerHello; similarly, a client can acknowledge a TLS HelloRetryRequest
-in the packet containing a second TLS ClientHello.  The complete set of server
-handshake messages (TLS ServerHello through to Finished) might be acknowledged
-by a client in protected packets, because it is certain that the server is able
-to decipher the packet.
-
+Implementations SHOULD aggressively ACK packets containing CRYPTO_HS frames.

Endpoints SHOULD send acknowledgments for packets containing CRYPTO_HS frames with a reduced delay; see Section 3.5.1 of {{RECOVERY}}.

+## NEW_TOKEN frame {#frame-new-token}
+
+An server sends a NEW_TOKEN frame (type=0x21) to provide the client a token to
+send in a the header of an Initial packet for a future 0-RTT connection.

~~0-RTT~~

+## NEW_TOKEN frame {#frame-new-token}
+
+An server sends a NEW_TOKEN frame (type=0x21) to provide the client a token to
+send in a the header of an Initial packet for a future 0-RTT connection.
+
+The NEW_TOKEN frame is as follows:
+
+~~~
+ 0                   1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|        Token Length (i)  ...

Alignment

+Offset:
+
+: A variable-length integer specifying the byte offset in the stream for the
+  data in this CRYPTO_HS frame.
+
+Length:
+
+: A variable-length integer specifying the length of the Crypto Data field in
+  this CRYPTO_HS frame.
+
+Crypto Data:
+
+: The cryptographic message data.
+
+There is a separate flow of cryptographic handshake data in each

Missing context: "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."

> +: A variable-length integer specifying the length of the Crypto Data field in
+  this CRYPTO_HS 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.
+
+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.

What do we do about extra Handshake messages on old epochs?  Those could be added to every epoch indefinitely, if it weren't for the fact that TLS would choke.  But I'm not entirely sure that it would choke if the handshake message were chosen carefully.

I'd double down and make this comprehensive.  We might have confusion about whether 0 is allowed if we don't say at least this much.

> @@ -3733,9 +3958,9 @@ Stream flow control, which prevents a single stream from consuming the entire
 receive buffer for a connection.
 
 A data receiver sends MAX_STREAM_DATA or MAX_DATA frames to the sender
-to advertise additional credit. MAX_STREAM_DATA frames send the maximum
-absolute byte offset of a stream, while MAX_DATA sends the maximum sum
-of the absolute byte offsets of all streams other than stream 0.
+to advertise additional credit. MAX_STREAM_DATA frames send the
+maximum absolute byte offset of a stream, while MAX_DATA sends the
+maximum of the sum of the absolute byte offsets of all streams.

👍 

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

---

From: ekr <[email-masked]>
Date: Tue, 19 Jun 2018 22:29:25 -0700

> At risk of this turning into a unicorn, here are my comments. I don't think that you need to address all of them, but I would appreciate you taking one pass through this so we don't have too many e…

I will do so directly. ETA tomorrow.

-- 
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#issuecomment-398628677

---

From: ianswett <[email-masked]>
Date: Wed, 20 Jun 2018 14:47:41 -0700

It's ack delay everywhere in this doc.

-- 
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#discussion_r196953259

---

From: ianswett <[email-masked]>
Date: Wed, 20 Jun 2018 14:48:51 -0700

This part is only about sending ACKs, but good point on the EndOfEarlyData.  As spec'd, that'd be TLP'd before being RTO'd, FYI.

-- 
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#discussion_r196953517

---

From: Christian Huitema <[email-masked]>
Date: Wed, 20 Jun 2018 19:58:09 -0700

huitema commented on this pull request.

Busy implementing this. It would be much easier to work draft-13 than parsing the PR...

I am busy implementing this, and I have a small issue with the "MAY appear in packets of any encryption level." How do I verify that the packets are sent as intended? For example, what if I receive a CRYPTO_HS frame with offset 500 in an  handshake-protected, and another CRYPTO_HS frame with an overlapping offset in an application-data protected packet?

I think there is a subtle interaction there between offset sequencing in CRYPTO_HS and per-stream packet sequence numbers.

This changes coalesced packets from an optional performance-oriented feature to an almost mandatory security related feature. We should make clear that sending coalesced packets is optional.  

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

---

From: Kazuho Oku <[email-masked]>
Date: Wed, 20 Jun 2018 20:07:42 -0700

> I am busy implementing this, and I have a small issue with the "MAY appear in packets of any encryption level." How do I verify that the packets are sent as intended? For example, what if I receive…

My assumption is that such check will be provided as an API or a guideline by the TLS stack, and that therefore it is unnecessary to clarify in the specification on how that should be done.

For example, the `ptls_handle_messages` function of [picotls](https://github.com/h2o/picotls/pull/141) accepts the epoch as the argument, and returns an error if a TLS messages was being received in an incorrect epoch.

-- 
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#discussion_r196999359

---

From: ekr <[email-masked]>
Date: Thu, 21 Jun 2018 07:17:43 -0700

@huitema: I don't understand what you are asking here, because those are different data namespaces.

So, for instance, SH will be sent with Handshake[Offset=0], and NST will be sent with Application[Offset=0]. They don't interact with each other.

The case that is an error is when data comes in at a given encryption level after the TLS state machine has moved on. For instance, if the server sends Handshake: [Offset=X, SFIN], Handshake: [Offset=X + len(SFIN), <something>]. This isn't valid because the TLS handshake is now reading at Application. As Kazuho says, this should generate an error, and the text requires that:

```
- 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.
```

-- 
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#discussion_r197150080

---

From: ekr <[email-masked]>
Date: Thu, 21 Jun 2018 11:04:27 -0700

@ekr pushed 3 commits.

d814642  Martin's comments
da0d8ec  Ensures that
89c45a6  Merge pull request #36 from ekr/ianswett-martin

-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/quicwg/base-drafts/pull/1450/files/954c585e680ca4bf8e2e18af57e5832b716d9fb7..89c45a658dc9cfe765d1252050f7874fe27bfd2f

---

From: ekr <[email-masked]>
Date: Fri, 22 Jun 2018 13:20:41 +0000 (UTC)

@ekr pushed 4 commits.

daea861  Address MT's comments on TLS
3aea50d  MT/Bishop comments on transport
bd5f9ff  Ian's comments
e2ed4db  Merge pull request #37 from ekr/martins_comments

-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/quicwg/base-drafts/pull/1450/files/89c45a658dc9cfe765d1252050f7874fe27bfd2f..e2ed4db7df7d72a08fe13b8da8d17f6fca601c26

---

From: ekr <[email-masked]>
Date: Fri, 22 Jun 2018 06:24:39 -0700

@martinthomson this addresses the comments on the PR. There are two points to call out:

1. There is some substantive back and forth about the model for how to describe the state of the TLS stack and the current encryption level it is reading from. I left some comments describing my view, but it might be easier to discuss live. I don't believe it actually affects bytes on the wire, except for a few points where I think you may have misunderstood, noted in my comments.
I didn't change that text.

2. In a number of places, I opted not to update the Retry text because it seems we are still working through the details on the list.

Done

Done

I am going to hold this for now. It's a simple sed script once we decide what this should say and CRYPTO_HS is easier to sed.

I disagree with you about the alerts, so let's pick that up on-list.

Leaving as-is

Leaving as-is.

Rewritten a bit.

Nothing needed at this time.

Doing nothing.

+

Done

Done.

+

Done.

Done

 ## Interface to TLS

Changed to "transmit and receive"

Done

-

I don't think that I agree with this.

Let's take send and receive separately. At any given time, the TLS stack is always sending with a given encryption level. That's just a fact of TLS, whether that's done by doing Rekey(); Send() or Send(Keys). In either case, the data is associated with that level when its sent to QUIC and QUIC needs to maintain that level upon transmission or retransmission.

Receive is more complicated: At any given time, the TLS stack is only prepared to receive packets at a given level. This is also a fact of TLS [0]. As you say, when a packet comes in, it is tagged with an encryption level and there are three cases:

- It's from a prior level, in which case it needs to be consistent with the existing data
- It's from the current level, in which case you process it
- It's from a future level, in which case you (probably) buffer it [I'm ignoring cases in which you packet that's impossibly from the future, like CFIN before you send SH.

Now, you can do this sorting/buffering operation at the TLS layer (like I think picoTLS does) or at the QUIC layer (like Minq does), but I think it's still true that there's one active level

[0] The only case in which this is confusing is 0-RTT rejection where the client is sending with Epoch 1 and the server is trying to receive with Epoch 0 or 2 (depending on how it was rejected). However, neither of these cases applies to QUIC, because you just don't enable the 0-RTT encryption level and so the packets are dropped prior to TLS.

Done

+

This doesn't seem right to me. First, the 0-RTT STREAM frame isn't relevant, because this is just about CRYPTO_HS.

As for EOED, here's what happens ordinarily (no loss)

- Recv CH; Rekey current RX to epoch 1
- Receive EOED: Rekey current RX to epoch 2
- Receive CFIN: Rekey current RX to epoch 3

If instead you get CH, CFIN, EOED, here's what happens:

- Recv CH; Rekey current RX to epoch 1
- Receive CFIN: it's in the future, so buffer
- Receive EOED: Rekey current RX to epoch 2
- Process CFIN; Rekey current RX to epoch 3

-                                                1-RTT Keys Ready
-                     <--- send/receive ---
+                      <------------ Initial
+                                          Rekey rx to 0-RTT keys

Leaving this pending the "current" discussion above.

Done.

Why? It seems like you could just start sending 0-RTT right then

Done.

Done

Added a reference to TLS 13.

-~~~
-struct {

Left.

replaced with comma.

Done.

Done

My intention was that this be completely separate, actually. 

With that said, I think there are a number of options here. I have the action item to talk to the cryptographers.

Rewritten a bit. The Retry thing is still in flux.

changed.

Done.

Done.

 

Done

are

 

I don't see what this has to do with EOED. Can you show me the packet flow you think has a problem here.

Done.

It's a Note.

Removed. I think this is old text, though.

I just removed it.

Done.

Done

Done

Done.

Done

Done

Done

 

Done

 

Done

I mostly-centered this. Is that what you wanted.

+~~~
+ 0                   1                   2                   3

Done.

I would expect it only on the first one, but leaving the text as-is, as this whole design seems a bit in flux.

+

Done.

+

Done.

+NEW_TOKEN frame.
+

Done

Did something here.

Done.

OK, though I see a lot of "random" in this document.

That's not actually correct, because you can use SCID=""

Done.

I think "a" is fine here.

Leaving as-is because in flux.

Done.

I'm going to leave it as-is for now.

+#### Tokens
+

Leaving b/c this design is in flux.

Done.

Good question. Seems like an open issue.

Done.

Done.

Leaving because in flux.

I prefer the current text.

Done.

I agree, but leaving because the design is in flux.

Done.

Done

Leaving, in flux.

Done.

Done.

Done.

Done.

Done,

I'm not following, so leaving.

I think I'm happier where it is, so I'm going to leave as-is and let you realize your vision when you want ti.

Done

Done.

+
+~~~~
+Client                                                  Server
+

Thanks. This was just a cut and paste error.

I don't know what you mean here.

Done.

Did a slightly more aggressive rewrite.

Done.

Done, but we need to work out the bigger design.

Done.

Done.

MAY

Done,

Done.

 

It actually is an interoperability requirement, because if you inadvertantly cross-ACK, you will have failures.

Done.

Done.

Done.

Done.

+Offset:
+

Added above.

+  this CRYPTO_HS frame.
+
+Crypto Data:
+

Hence the text above that forbids stuff extending past the end.

+of data.
+

Sent as left-padded for now. I know MT wants to argue about this whole structure.

Done.

Left as-is.

Done.

 

Done,

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

---

From: Mike Bishop <[email-masked]>
Date: Fri, 22 Jun 2018 15:37:20 -0700

@MikeBishop pushed 1 commit.

7a780db  Fix build breaks

-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/quicwg/base-drafts/pull/1450/files/e2ed4db7df7d72a08fe13b8da8d17f6fca601c26..7a780dbed8eed8ed9584db89215bd752dbf86c7a

---

From: Mike Bishop <[email-masked]>
Date: Fri, 22 Jun 2018 15:54:18 -0700

4db5568  Extra word

-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/quicwg/base-drafts/pull/1450/files/7a780dbed8eed8ed9584db89215bd752dbf86c7a..4db556887313b51de0139bb7c6c7be33614c4ddb

---

From: Martin Thomson <[email-masked]>
Date: Sun, 24 Jun 2018 17:48:05 -0700

24h warning.

There are a number of things that this text leaves open, and in some cases things are broken (see esp. Retry), but we can't afford to leave this open any longer.  If you have new issues; this isn't the place to discuss them.  It's OK to open a new issue with the assumption that this PR will be merged, because it will be.  (I'll take some of the open comments here and make issues.  It looks like we already have issues for the Retry problems.)

-When the alarm fires, the sender MUST retransmit all unacknowledged handshake
-data, by calling RetransmitAllUnackedHandshakeData(). On each consecutive
-firing of the handshake alarm, 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.

Is this encryption level or packet number space?

Also, the first SHOULD in the previous paragraph needs at least one caveat for this case.

> @@ -422,6 +441,14 @@ sending any ACK frames in response.  In this case they can determine
 
+### 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

The MAY is weird.  ACK can always be sent immediately.

+consists of a contiguous block of handshake data identified by an
+offset and length. Those frames are packaged into QUIC packets

We use "encryption level" rather than sending keys, but I don't think that either works very well for this; TLS has a strict notion of what should be used to protect every octet, but there are multiple of these contexts in flight at the same time.  Needs work.

I agree with Christian here.  Nothing says that sending together is necessary, no matter how good it might be for performance.

-

I see.  The problem here is that I was thinking QUIC, and this really applies to TLS.  TLS assumes ordering, but QUIC doesn't.  That's something that needs to be improved here, but I don't think that we need to do that here.

 

My point is that you can't cross-ACK because you aren't capable of acknowledging something in a different packet number space.

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

---

From: Martin Thomson <[email-masked]>
Date: Sun, 24 Jun 2018 18:45:24 -0700

@martinthomson pushed 1 commit.

8d57711  remove "the the"

-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/quicwg/base-drafts/pull/1450/files/4db556887313b51de0139bb7c6c7be33614c4ddb..8d57711c819307c44cec8db2964a2a80c8f87ab9

---

From: Martin Thomson <[email-masked]>
Date: Sun, 24 Jun 2018 18:58:17 -0700

a2aabfe  More errors around delivering to TLS out of order

-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/quicwg/base-drafts/pull/1450/files/8d57711c819307c44cec8db2964a2a80c8f87ab9..a2aabfe9e6feec0eaab59af0f4a0c212190b4474

---

From: Martin Thomson <[email-masked]>
Date: Sun, 24 Jun 2018 19:02:11 -0700

2473966  The online editor is terrible

-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/quicwg/base-drafts/pull/1450/files/a2aabfe9e6feec0eaab59af0f4a0c212190b4474..2473966033d8f2d75a37113e723d05be42b20f38

---

From: ekr <[email-masked]>
Date: Sun, 24 Jun 2018 19:26:26 -0700

@ianswett: ^^?

-- 
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#discussion_r197666160

---

From: ekr <[email-masked]>
Date: Sun, 24 Jun 2018 19:26:37 -0700

It does seem like this should be a SHOULD

-- 
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#discussion_r197666178

---

From: ekr <[email-masked]>
Date: Sun, 24 Jun 2018 19:31:10 -0700

I guess this may be a terminology issue. Let me try to explain what I am saying again.
 
Say I receive the following packets 2:1, 2:2, 3:1, 3:3 where X:Y means "epoch X, PN Y". And then I screw up and ACK PN space 3 in epoch 2, so I send epoch=2: ACK[3, 1]. Technically, this means "Acknowledge PNs 3 and 1 in epoch 2", so it's not a cross-ACK from the receiver's perspective, but it *is* an ACK of an unsent packet, which at least at some times we have thought was grounds for tearing down a connection.

-- 
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#discussion_r197666543

---

From: Martin Thomson <[email-masked]>
Date: Sun, 24 Jun 2018 20:58:27 -0700

martinthomson commented on this pull request.

 

Yeah, I think that there are two statements to make, each of which differs from the one you chose.

1. An endpoint MUST NOT acknowledge packets you haven't received (and processed).
2. An ACK frame can only acknowledges packets from the same packet number space.

The conjunction of these two things is what you are getting at: if you receive a packet in one packet number space, you cannot acknowledge it in a different space because that would be acknowledging a different packet, one you might not have received.

-- 
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#discussion_r197674413

---

From: ianswett <[email-masked]>
Date: Mon, 25 Jun 2018 08:23:56 -0700

I was intending it to be encryption level, since I thought it was necessary to send end of early data in a timely manner?  But maybe it doesn't matter that much? 

It's possible a signal that the handshake is complete would be preferable to monitoring what encryption level CRYPTO_HS is sent at, but I'll just make it consistent for now.

-- 
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#discussion_r197837633

---

From: Martin Thomson <[email-masked]>
Date: Mon, 25 Jun 2018 16:34:59 -0700

Sounds reasonable.  I just wanted to check.  And yeah, we probably need to send EndOfEarlyData quickly.  It blocks access to 1-RTT data just like Finished.

-- 
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#discussion_r197973976

---

From: Martin Thomson <[email-masked]>
Date: Mon, 25 Jun 2018 16:52:28 -0700

Merged #1450.

-- 
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#event-1700170756