Subject: [quicwg/base-drafts] Invert connection ID (#493)

From: Martin Thomson <[email-masked]>
Date: Wed, 03 May 2017 03:39:15 -0700

This defines a new packet type for the initial client cleartext packet, and stateless rejects.  The remaining packets that carry cleartext messages remain the same.  The final packet from the server is removed; instead the server cleartext packet carries the server-selected connection ID.  The server can propose a new connection ID in any of its cleartext packets, including the version negotiation packet.

This rolls in the changes from #482 and so addresses the issues raised there.

Things that I might do differently: 

1. Require the client to send an initial packet after version negotiation on the basis that version negotiation is a complete do-over.  

2. Maybe also after a stateless reject, which would mean that all packets containing the ClientHello would use that "initial" type.  That would mean that only the initial type would have packet size restrictions,
which is nice.

Those alternatives give the server more options for changing connection ID as well, but it also removes the ability for a server-side load balancer to easily distinguish between connection IDs that the client proposes and those that the server has provided.  Not sure which way that goes, I've opted to keep the signal in place until we've had some more discussion.

Closes #482, #442.
You can view, comment on, or merge this pull request online at:

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

-- Commit Summary --

  * Address validation is stateless reject
  * Expand description
  * Rework cleartext packet descriptions
  * Merge branch 'stateless_reject' into invert_connection_id
  * Expand on HelloRetryRequest rules

-- File Changes --

    M draft-ietf-quic-tls.md (33)
    M draft-ietf-quic-transport.md (281)

-- Patch Links --

https://github.com/quicwg/base-drafts/pull/493.patch
https://github.com/quicwg/base-drafts/pull/493.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/493

---

From: MikkelFJ <[email-masked]>
Date: Wed, 03 May 2017 03:43:00 -0700

mikkelfj commented on this pull request.

>  location in all packet headers, making it straightforward for middleboxes, such
 as load balancers, to locate and use it.
 
-When a connection is initiated, the client MUST choose a random value and use it
-as the initial Connection ID until the final value is available. The initial
-Connection ID is a suggestion to the server. The server echoes this value in all
-packets until the handshake is successful (see {{QUIC-TLS}}). On a successful
-handshake, the server MUST select the final Connection ID for the connection and
-use it in Final Server Cleartext packets. This final Connection ID MAY be the
-one proposed by the client or MAY be a new server-selected value. All subsequent
-packets from the server MUST contain this value.  On handshake completion, the
-client MUST switch to using the final Connection ID for all subsequent
-packets.
+The client MUST choose a random connection ID and use it in Client Initial
+packets ({{packet-client-initial}}).  If the client has received any packet from
+the server, the uses the connection ID it received from the server in that
+packet.

typo: the uses 

-- 
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/493#pullrequestreview-35986681

---

From: Martin Thomson <[email-masked]>
Date: Wed, 03 May 2017 03:44:25 -0700

martinthomson commented on this pull request.

thanks, fixed

-- 
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/493#discussion_r114516035

---

From: MikkelFJ <[email-masked]>
Date: Wed, 03 May 2017 03:45:13 -0700

Need to read this more carefully - but seems to solve some issues. However, is there any good reason for not providing the initial client id in a server response when the id has been updated? It would greatly simplify some implementations.

-- 
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/493#issuecomment-298877968

---

From: Martin Thomson <[email-masked]>
Date: Wed, 03 May 2017 03:55:43 -0700

Not sure that I follow the question, are you suggesting that the server messages have two connection ids, one that echoes the client's value and one that is the server's value?

-- 
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/493#issuecomment-298879873

---

From: MikkelFJ <[email-masked]>
Date: Wed, 03 May 2017 04:08:48 -0700

yes, exactly

-- 
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/493#issuecomment-298882180

---

From: Jānis <[email-masked]>
Date: Wed, 03 May 2017 06:31:26 -0700

1. Just an idea - what if quic wouldn't rely on TLS for initial stateless client address verify, but would define its own special pack type which includes cookie + ClientHello? That way server implementation wouldn't need to init TLS before client validated and quic wouldn't have to 'detect' that TLS has responded with HelloRetryRequest. NOTE that I haven't fully understood if that would impact other uses of HelloRetryRequest or quic states. (just an idea)

2. Changing connection ID on initial client connection could be great for server side load balancing, because 'newly connected' clients can be routed to  servers that process the slow handshake process. In case there is an DDOS which starts many TLS handshakes, they are only affecting new client connections, but the existing ones can't be attacked so easily. Or just to simply route(load balance) new client to free server.

-- 
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/493#issuecomment-298911259

---

From: mirjak <[email-masked]>
Date: Wed, 03 May 2017 09:44:27 -0700

Back to @mikkelfj question: I think it might make sense to sort out the different use cases for the connection ID and think about those and the required properties separately. From my understanding we have three use cases:
1) as input for stateless load balancers
2) as confirmation signal
3) for connection migration

For 1) the id must be chosen by the server (or the load balancer) and must be visible to the load balancer on every packet; however, this id does actually not have to be unique for the connection. It rather identifies the server and as such could effectively be the same for all connections that go to the same server.

For 2) a value is selected by the client and reflected by the server. The signal may be visible to the path as it can be used to set up state e.g. for firewalls. Probably this signal is only needed at connection start or some kind of restart, however, exposing it all the time would potentially allow for transparent rebinding if state got lost on the path. Note the packet number echo could fulfil the same purpose. 

For 3) server and client must have agreed to a token. This signal does not necessarily need to be exposed to the path because the path might have changed anyway. However, it cannot easily be encrypted either as this is needed to identify the right encryption context. Effectively it only needs to be sent after the migration but the endpoint might not know if the migration happen, so not sending it all the time could lead to a one RTT delay after migration to request it. 

Hope that helps!

(credits for this analysis actually go to Jean-Pierre Smith, one of Brian's colleges in the network security group) 

-- 
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/493#issuecomment-298967891

---

From: MikkelFJ <[email-masked]>
Date: Wed, 03 May 2017 09:57:53 -0700

@mirjak 

The use case I have in mind is not fully covered in the above three cases:

4) As a unique identifier for associating connection state. Without a unique id this is handled via IP:port  until connection migration, then replaced with a new IP:port. This requires IP:port to be unique to the respective end-points (when connection id does not serve that purpose).

In praxis the Connection ID will serve the purpose of associating connection state, but when not explicitly statet, there are gaps, such as during initial setup.

Ensuring a Connection ID all the way in public headers - either a single (client selected), or a replaced (client->server->client replaced), makes it possible to find connection state at end-points before decryption without relying on port associations. Obviously this will not work with short headers that exclude the connection 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/493#issuecomment-298971546

---

From: Martin Thomson <[email-masked]>
Date: Wed, 03 May 2017 14:40:27 -0700

@mikkelfj, not sure what you would gain by doing that.

-- 
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/493#issuecomment-299043736

---

From: Martin Thomson <[email-masked]>
Date: Wed, 03 May 2017 15:13:55 -0700

@mirjak, I don't think that we require the connection ID as a confirmation signal.  In fact, none of the existing designs (this proposal, or what is in the draft) actually provide that in all cases.  I agree that it is double double duty regarding load balancers and migration, but that could be more generically referred to as "ensuring the packet ends up where it should".

@mikkelfj, I think that you are right with your fourth use case; it's the generalization above.  However, the notion of identification is subtly dangerous.  The goal is not so much to identify a connection, but ensure that packets arrive at the right place.  Identification implies some sort of permanence.

The model that I think we have here isn't perfectly symmetrical.  For the client, the 5-tuple is what ensures that packets arrive at the right place.  The server uses the connection ID, which allows the client to migrate.  In theory, the server can migrate, but not during the handshake, and not at the same time as the client, but this probably won't work in practice if you concede that certain types of middlebox are commonplace on the client ends of connections.  You can see this in practice with most Google clients allowing the server to omit the connection 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/493#issuecomment-299050741

---

From: MikkelFJ <[email-masked]>
Date: Wed, 03 May 2017 15:50:53 -0700

On permanency: I'm fine with changing ID as long as the new ID can be passed encrypted in a packet identified using the old ID, or with the old ID publicly in a packet with a new ID.

On client server behavior - there are symmetric use cases where client / server as a concept makes little sense other than who runs the handshake. Interfaces (IP address) may also be hard to predict in certain environments, or it may be beneficial to fire on all available interfaces - for example given multiple network cards. Overlay mesh networks can route traffic on random identifiers or content based hashing. The fixed IP nature is far from a given in complex IoT mesh networks with no central routing capabilities. I'm not saying QUIC should automatically support this, but if all it takes is adding an ID to a handshake, then it is worth a thought.

-- 
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/493#issuecomment-299057489

---

From: MikkelFJ <[email-masked]>
Date: Wed, 03 May 2017 16:05:56 -0700

On changing ID - this could force a client, or server, to maintain state and payload for unknown ID packets until it recieves a change instruction or decides that none will arrive. Thus an attack could inject random IDs with random but seemingly encrypted content. Which of course is more difficult when tied to a 5-tuple.

-- 
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/493#issuecomment-299060065

---

From: Martin Thomson <[email-masked]>
Date: Wed, 03 May 2017 19:26:06 -0700

@chocis,

> what if quic wouldn't rely on TLS for initial stateless client address verify, but would define its own special pack type which includes cookie + ClientHello?

The problem here is that it can lead to yet another round trip in the degenerate case.  Currently we have a worst-case handshake that is three round trips: version negotiation, stateless reject, and the 1-RTT handshake.  Adding address validation to QUIC means that TLS might add a key share round trip to that unless we did something special.  It also means creating just as many new packet types along with some new mechanisms, some of which duplicate other features.

-- 
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/493#issuecomment-299084001

---

From: janaiyengar <[email-masked]>
Date: Wed, 03 May 2017 23:34:52 -0700

janaiyengar commented on this pull request.

I really like this set of changes! It does streamline things quite a bit. A few comments inline.

> +needs to be able recover the hash of the ClientHello and its length, plus any
+information it needs in order to reconstruct the HelloRetryRequest.
+
+
+### Sending HelloRetryRequest
+
+A server does not need to maintain state for the connection when sending a
+HelloRetryRequest message.  This might be necessary to avoid creating a denial
+of service exposure for the server.  However, this means that information about
+the transport will be lost at the server.  This includes the stream offset of
+stream 0, the packet number that the server selects, and any opportunity to
+measure round trip time.
+
+A server MUST send a TLS HelloRetryRequest in a Server Stateless Retry packet.
+Using a Server Stateless Retry packet causes the client to reset stream offsets
+and avoids the need to commit to an initial packet number.

I don't follow -- what is the client avoiding "committing" to?

> +### Sending HelloRetryRequest
+
+A server does not need to maintain state for the connection when sending a
+HelloRetryRequest message.  This might be necessary to avoid creating a denial
+of service exposure for the server.  However, this means that information about
+the transport will be lost at the server.  This includes the stream offset of
+stream 0, the packet number that the server selects, and any opportunity to
+measure round trip time.
+
+A server MUST send a TLS HelloRetryRequest in a Server Stateless Retry packet.
+Using a Server Stateless Retry packet causes the client to reset stream offsets
+and avoids the need to commit to an initial packet number.
+
+A HelloRetryRequest message MUST NOT be split between multiple Server Stateless
+Retry packets.  This means that HelloRetryRequest is subject to the same size
+constraints as a ClientHello (see {{clienthello-size}}).

Huh -- perhaps this should always have been a requirement

-* Octet 0: 0x81
-* Octets 1-8: Connection ID (echoed)
-* Octets 9-12: Packet Number (echoed)
-* Octets 13-16: Version (echoed)
-* Octets 17+: Payload
+The connection ID field contains a connection ID that the client should use for

suggestion: "contains a server-chosen connection ID"

-* Octet 0: 0x81
-* Octets 1-8: Connection ID (echoed)
-* Octets 9-12: Packet Number (echoed)
-* Octets 13-16: Version (echoed)
-* Octets 17+: Payload
+The connection ID field contains a connection ID that the client should use for
+subsequent packets, see {{connection-id}}.
+
+The packet number and version fields contain the values from the client packet
+that triggered the Version Negotiation packet.  This allows clients some

suggested reword: "The packet number and version fields echo corresponding values from the triggering client packet."

-* Octet 0: 0x81
-* Octets 1-8: Connection ID (echoed)
-* Octets 9-12: Packet Number (echoed)
-* Octets 13-16: Version (echoed)
-* Octets 17+: Payload
+The connection ID field contains a connection ID that the client should use for
+subsequent packets, see {{connection-id}}.
+
+The packet number and version fields contain the values from the client packet
+that triggered the Version Negotiation packet.  This allows clients some
+assurance that the server received the packet and that the Version Negotiation
+packet does not contain a spoofed source address.

The version negotiation packet does not contain any source address

-* Octet 0: 0x82
-* Octets 1-8: Connection ID (initial)
-* Octets 9-12: Packet number
-* Octets 13-16: Version
-* Octets 17+: Payload
+Cleartext packets all contain the current QUIC version in the version field.

nit: "All cleartext packets", not "Cleartext packets all"

-Non-Final Server Cleartext packets contain:
+The packet number is randomized for the Client Initial packet
+({{packet-client-initial}} and the first Server Cleartext packet
+({{packet-server-cleartext}}).  It increases by one for each packet sent
+thereafter, see {{packet-numbers}} for details.  The Server Stateless Retry
+packet ({{packet-server-stateless}}) contains the packet number of the packet
+that it is responding to.

editorial nit: move all these to the corresponding sections? I think the packet descriptions should be the place we describe type-specific details.

-The payload of a Cleartext packet consists of a sequence of frames, as described
-in {{frames}}.  Cleartext packets also include an integrity check, described in
-{{QUIC-TLS}}.
+The client populates the connection ID and packet number fields with randomly
+selected values.  The randomized packet number is incremented for each

Just "packet number" -- If the packet number is incremented for each subsequent packet, it's not randomized.

-The payload of a Cleartext packet consists of a sequence of frames, as described
-in {{frames}}.  Cleartext packets also include an integrity check, described in
-{{QUIC-TLS}}.
+The client populates the connection ID and packet number fields with randomly
+selected values.  The randomized packet number is incremented for each
+subsequent packet (see {{packet-numbers}}).
+
+The payload of a Client Initial packet consists of a STREAM frame (or frames)
+for stream 0 containing a cryptographic handshake message, plus PADDING frames
+that increase the size of the packet to a minimum size (see {{packetization}}).

"to larger than a minimum size" ?

-The payload of a Cleartext packet consists of a sequence of frames, as described
-in {{frames}}.  Cleartext packets also include an integrity check, described in
-{{QUIC-TLS}}.
+The client populates the connection ID and packet number fields with randomly
+selected values.  The randomized packet number is incremented for each
+subsequent packet (see {{packet-numbers}}).
+
+The payload of a Client Initial packet consists of a STREAM frame (or frames)
+for stream 0 containing a cryptographic handshake message, plus PADDING frames
+that increase the size of the packet to a minimum size (see {{packetization}}).
+
+The client uses the Client 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, either
+in response to a Version Negotiation packet, in response to a stateless retry

missing "or"

> +packet containing the initial cryptographic message needs to be created, either
+in response to a Version Negotiation packet, in response to a stateless retry
+({{packet-server-stateless}}).
+
+
+### Server Stateless Retry Packet {#packet-server-stateless}
+
+A Server Stateless Retry packet has a type octet of 0x83.  It carries
+cryptographic handshake messages and acknowledgments.  It is used by a server
+that wishes to perform a stateless retry (see {{stateless-retry}}).
+
+The connection ID field in a Server Stateless Retry packet contains a server
+selected value, see {{connection-id}}.
+
+The packet number contains the packet number from the packet that caused it to
+be sent.  This allows a client to verify that the server received its packet.

Reword this sentence. Perhaps "The packet number field echoes the packet number of the triggering client packet."

> +be sent.  This allows a client to verify that the server received its packet.
+
+After receiving a Server Stateless Retry packet, the next cryptographic
+handshake message MUST be sent by the client on stream 0 at an offset of 0.  The
+client discards any buffers it uses for generating retransmissions of handshake
+data and effectively starts the connection anew, keeping only the cryptographic
+handshake state.  The cryptographic handshake is continued, but the transport
+connection is reset.  Continuing the cryptographic handshake is necessary to
+ensure that an attacker cannot force a downgrade of any cryptographic
+parameters.
+
+The client constructs a new Client Cleartext packet
+({{packet-client-cleartext}}) for subsequent cryptographic handshake messages.
+
+The payload of this packet contains STREAM frames and could contain PADDING and
+ACK frames.

Swap the order of these last two paragraphs, since "this packet" is ambiguous in this last para, and since the note about Client Cleartext packet fits just before the next section.

> +
+The client constructs a new Client Cleartext packet
+({{packet-client-cleartext}}) for subsequent cryptographic handshake messages.
+
+The payload of this packet contains STREAM frames and could contain PADDING and
+ACK frames.
+
+
+### Client Cleartext Packet {#packet-client-cleartext}
+
+A Client Cleartext packet has a type octet of 0x84 and is sent when the client
+has received a packet from the server, which will be either a Server Cleartext
+packet or a Version Negotiation packet.
+
+The connection ID field in a Client Cleartext packet contains a connection ID
+that was selected by the server (see {{connection-id}}).

reword: "The connection ID in a Client Cleartext packet is the server-selected one from the server packet."

+The payload of this packet contains STREAM frames and could contain PADDING and
+ACK frames.  If this packet is sent in response to a Version Negotiation
+({{packet-version}}) or Server Stateless Retry packet
+({{packet-server-stateless}}), it MUST be padded to the minimum packet size for

This should be the same size as the Client Initial packet, otherwise the packet may not get through, due to path MTU.

-A first octet of 0x85 indicates a 0-RTT packet. After the 1-RTT keys are
-established, key phases are used by the QUIC packet protection to identify the
-correct packet protection keys. The initial key phase is 0. See {{QUIC-TLS}} for
-more details.
+The connection ID field in a Server Cleartext packet contains a connection ID
+that is chosen by the server (see {{connection-id}}).

"The connection ID in a Server Cleartext packet is chosen by the server, and it is used by both the server and the client in subsequent packets."

IIUC, the connection ID MUST be the same as in the client packet when sent in response to a Client Cleartext packet, and MUST be server chosen when sent in response to an Initial Client packet. If so, I would clarify that here.

-A first octet of 0x85 indicates a 0-RTT packet. After the 1-RTT keys are
-established, key phases are used by the QUIC packet protection to identify the
-correct packet protection keys. The initial key phase is 0. See {{QUIC-TLS}} for
-more details.
+The connection ID field in a Server Cleartext packet contains a connection ID
+that is chosen by the server (see {{connection-id}}).
+
+The payload of this packet contains STREAM frames and could contain PADDING and
+ACK frames.
+
+
+## Encrypted Packets {#packet-encrypted}
+
+Packets that are protected with 0-RTT packets are sent with long headers.

typo: 0-RTT keys, not packets

> -established, key phases are used by the QUIC packet protection to identify the
-correct packet protection keys. The initial key phase is 0. See {{QUIC-TLS}} for
-more details.
+The connection ID field in a Server Cleartext packet contains a connection ID
+that is chosen by the server (see {{connection-id}}).
+
+The payload of this packet contains STREAM frames and could contain PADDING and
+ACK frames.
+
+
+## Encrypted Packets {#packet-encrypted}
+
+Packets that are protected with 0-RTT packets are sent with long headers.
+Packets that are protected with 1-RTT keys MAY be sent with long headers.  The
+different packet types explicitly indicate the encryption level and therefore
+the keys that are used to remove packet protection.

"to remove packet protection" --> "for decryption"?

> +
+Packets that are protected with 0-RTT packets are sent with long headers.
+Packets that are protected with 1-RTT keys MAY be sent with long headers.  The
+different packet types explicitly indicate the encryption level and therefore
+the keys that are used to remove packet protection.
+
+Packets protected with 0-RTT keys use a type octet of 0x85.  The connection ID
+field for a 0-RTT packet is selected by the client, unless the client has
+received a packet from the server.  The client can send 0-RTT packets after
+having received a packet from the server if that packet does not complete the
+handshake.  If the client has received a packet, it MAY update the connection ID
+it uses for 0-RTT packets.
+
+Packets protected with 1-RTT keys use a type octet of 0x86 for key phase 0 and
+0x87 for key phase 1; see {{QUIC-TLS}} for more details on the use of key
+phases.  The connection ID field for these packet types contains the value

"MUST contain"

> @@ -642,27 +708,27 @@ TODO: Details to be added.
 
 ## Connection ID {#connection-id}
 
-QUIC connections are identified by their 64-bit Connection ID. All long headers
-contain a Connection ID. Short headers indicate the presence of a Connection ID
-using the CONNECTION_ID flag. When present, the Connection ID is in the same
+QUIC connections are identified by their 64-bit Connection ID.  All long headers
+contain a Connection ID.  Short headers indicate the presence of a Connection ID
+using the CONNECTION_ID flag.  When present, the Connection ID is in the same

nit: extra whitespace after period in 3 sentences above.

> @@ -1131,7 +1197,34 @@ version negotiation occurred but it would have selected a different version
 based on the value of the supported_versions list.

-## Proof of Source Address Ownership {#source-address-token}
+## Stateless Retries {#stateless-retry}
+
+A server can process a the initial cryptographic handshake messages from a

typo: "a the"

> +A server can process a the initial cryptographic handshake messages from a
+client without committing any state.  This allows a server to perform address
+validation ({{address-validation}}, or to defer connection establishment costs.
+
+In order to ensure consistent state regarding stream offsets and packet numbers,
+a server that generates a response to an initial packet without retaining
+connection state MUST use the Server Stateless Retry packet
+({{packet-server-stateless}}).  This packet causes a client to reset the state
+of stream 0 and continue the connection attempt with fresh stream state while
+maintaining the state of the cryptographic handshake.
+
+A server that sends a Server Stateless Retry packet is then not obligated to
+ensure that it correctly accounts for data already sent on stream 0 either by
+both itself or by the client.  Similarly, a server also does not have to
+remember a randomized initial packet number: the Server Stateless Retry packet
+includes a copy of the packet number from the client packet.

Why's the randomized initial number stored in the cookie? Since this is effectively a new connection, the client could use a completely new random packet number, no?

> +In order to ensure consistent state regarding stream offsets and packet numbers,
+a server that generates a response to an initial packet without retaining
+connection state MUST use the Server Stateless Retry packet
+({{packet-server-stateless}}).  This packet causes a client to reset the state
+of stream 0 and continue the connection attempt with fresh stream state while
+maintaining the state of the cryptographic handshake.
+
+A server that sends a Server Stateless Retry packet is then not obligated to
+ensure that it correctly accounts for data already sent on stream 0 either by
+both itself or by the client.  Similarly, a server also does not have to
+remember a randomized initial packet number: the Server Stateless Retry packet
+includes a copy of the packet number from the client packet.
+
+A server MUST NOT send multiple Server Stateless Retry packets in response to a
+client handshake packet.  Thus, any cryptographic handshake message that is used
+MUST fit within a single packet.

nit: "that is used" --> "that is sent"

-- 
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/493#pullrequestreview-36168899

---

From: Martin Thomson <[email-masked]>
Date: Thu, 04 May 2017 00:15:19 -0700

The server is the one that commits.  The problem is that a client that receives a regular packet would expect the next regular packet to appear at the next packet number.  By sending a regular packet, the server commits to that.  I'll clarify.

-- 
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/493#discussion_r114711018

---

From: Martin Thomson <[email-masked]>
Date: Thu, 04 May 2017 00:16:56 -0700

+

Well, yeah :)  I sort of realized that here.

Note that there is an idea floating around for a faster stateless reject.  In that idea, you send a complete handshake and a session ticket, then close the connection.  It allows the client to make a new connection and use 0-RTT, which is actually faster than the stateless reject we define.  It's massively more costly though, and it wouldn't fit this pattern.

-- 
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/493#discussion_r114711219

---

From: janaiyengar <[email-masked]>
Date: Thu, 04 May 2017 00:21:17 -0700

The server has no way of ensuring that the Client Cleartext packet contains the server's chosen connection ID. A bold client *could* start a connection with a random (or if nefarious, a targeted) connection ID with a Client Cleartext packet, defeating one of the purposes of server-chosen connection IDs.

I'll argue for two things to change. (i) I think we should make both the changes you propose -- that a Client Initial packet be sent right after both Version Negotiation and Stateless Retry packets. (ii) 0-RTT packets MUST contain the same connection ID as in the client's most recent handshake packet to make it possible for load balancers to work with them. 

With these changes, a server treats all Client Initial packets similarly, in that it responds to them with a new server-chosen connection ID. Load balancers treat all Client Initial, Client Cleartext, and 0-RTT packets as containing a client-chosen connection ID, and other packets as containing server-chosen connection IDs.

One of the purposes of this change is to enable a server to direct a client towards a particular server via the connection ID in a Version Negotiation or a Stateless Retry packet. A server can still do that by generating a connection ID that it knows will hash to the right server. Basically, load balancers will use two functions for hashing connection ID -- C() to hash client-chosen connection IDs and S() for server-chosen ones. On a VN or SR packet, the server needs to generate and send a connection ID so that C(connection ID) sends the retrying client to the desired server. This allows a server to redirect while also allowing the server infrastructure to not trust that a client is doing the right thing.

-- 
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/493#issuecomment-299113570

---

From: Martin Thomson <[email-masked]>
Date: Thu, 04 May 2017 00:22:01 -0700

-* Octet 0: 0x81

heh, oops

-- 
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/493#discussion_r114711855

---

From: Martin Thomson <[email-masked]>
Date: Thu, 04 May 2017 00:22:38 -0700

Done, it got complicated, then I wasn't sure about duplication...

-- 
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/493#discussion_r114711922

---

From: Martin Thomson <[email-masked]>
Date: Thu, 04 May 2017 00:29:57 -0700

That seems worse, I've gone with:  "The connection ID field in a Client Cleartext packet contains a server-selected connection ID, see {{connection-id}}."  Less detail, less cumbersome.

-- 
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/493#discussion_r114712855

---

From: Martin Thomson <[email-masked]>
Date: Thu, 04 May 2017 00:31:09 -0700

OK, so technically the text I have would allow it to be reduced in size as long as it was still above the protocol-defined minimum.  I think that's 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/493#discussion_r114713000

---

From: Martin Thomson <[email-masked]>
Date: Thu, 04 May 2017 00:32:27 -0700

Yeah, I was finagling a little here.  If we go with the change I suggested, that will be a moot point.  The server can pick a new one here too.

-- 
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/493#discussion_r114713197

---

From: Martin Thomson <[email-masked]>
Date: Thu, 04 May 2017 00:36:28 -0700

decryption is too imprecise unfortunately, this is the term we use in TLS because it is what an AEAD does

-- 
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/493#discussion_r114713692

---

From: Martin Thomson <[email-masked]>
Date: Thu, 04 May 2017 00:37:01 -0700

You only just noticed?

-- 
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/493#discussion_r114713775

---

From: Martin Thomson <[email-masked]>
Date: Thu, 04 May 2017 00:38:05 -0700

Right, the text says that the server does not have to remember the packet number, see earlier discussion.

-- 
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/493#discussion_r114713896

---

From: Martin Thomson <[email-masked]>
Date: Thu, 04 May 2017 03:57:55 -0700

@martinthomson pushed 3 commits.

4ccdbe8  Tidy up grammar
ef61357  Jana's review comments
93d4eaa  Reset more completely for stateless retry and version negotiation

-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/quicwg/base-drafts/pull/493/files/beb33da6b62830f8ded373982f1178450e8732d2..93d4eaa2178ba9c8debf9bc23528e34c241fc844

---

From: janaiyengar <[email-masked]>
Date: Thu, 04 May 2017 15:40:58 -0700

It's being flagged with a "darker green" color -- are these tabs?

-- 
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/493#discussion_r114903923

---

From: Martin Thomson <[email-masked]>
Date: Thu, 04 May 2017 18:30:12 -0700

Probably spaces that were added when I reflowed the paragraph.

-- 
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/493#discussion_r114920492

---

From: MikkelFJ <[email-masked]>
Date: Fri, 05 May 2017 07:26:51 -0700

I must admit that I am not aware of all the details influencing how the connection id is being used, but I had this idea:

What if each endpoint is allowed to choose their own connection id and stick it? This would mean that packets send from client to server would use one ID, and packets sent from server to client would use another ID. This will impact middle boxes, but not necessarily in a bad way.

Although this is not the original intent for the connection ID such a design would make it possible to remove IP and UDP headers on custom networks, such as IoT mesh networks. Here the connection ID would be the routable address. That would not work without a notion of direction with the shared connection ID.

Wrt. rotating connection ID, it could be required that an endpoint does not start using a new ID before a frame has been ack'ed in which the transtion from old to new ID has been communicated - with special handling for initial setup where server echoes inital client ID in early packets. If this ACK is not used, an end-point may have to cache data until it can make an association from old to new data and this could be abused.

-- 
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/493#issuecomment-299479343

---

From: janaiyengar <[email-masked]>
Date: Mon, 08 May 2017 17:15:59 -0700

I'll respond on the email thread in a bit, but some comments from a re-read

-The client MUST choose a random 64-bit value and use it as the initial
-Connection ID in all packets until the server replies with the final Connection
-ID. The server echoes the client's Connection ID in Non-Final Server Cleartext
-packets.  The first Final Server Cleartext and all subsequent packets MUST use
-the final Connection ID, as described in {{connection-id}}.
+The packet number used for Client Initial packets is initialized with a random
+value each time the new contents are created for the packet.  Retransmissions of

nit: drop "the" in "the new contents"

-The client MUST choose a random 64-bit value and use it as the initial
-Connection ID in all packets until the server replies with the final Connection
-ID. The server echoes the client's Connection ID in Non-Final Server Cleartext
-packets.  The first Final Server Cleartext and all subsequent packets MUST use
-the final Connection ID, as described in {{connection-id}}.
+The packet number used for Client Initial packets is initialized with a random
+value each time the new contents are created for the packet.  Retransmissions of
+the packet contents increment the packet number by one, see
+({{packet-numbers}}).

I think we should just say that all transport state is reset on receiving a Version Negotiation or a Stateless Retry packet. That should make it possible to not have to distinguish between the packet numbers here.

+
+### Server Stateless Retry Packet {#packet-server-stateless}
+
+A Server Stateless Retry packet has a type octet of 0x83.  It carries
+cryptographic handshake messages and acknowledgments.  It is used by a server
+that wishes to perform a stateless retry (see {{stateless-retry}}).
+
+The connection ID field in a Server Stateless Retry packet contains a server
+selected value, see {{connection-id}}.
+
+The packet number field echoes the packet number of the triggering client
+packet.  This allows a client to verify that the server received its packet.
+
+After receiving a Server Stateless Retry packet, the client MUST generate a new
+Client Initial packet containing the next cryptographic handshake message.  The

I think we should state that the client MUST reset all connection state at this point, simplifying this description. ... and you do say it below, but I'd just say that and drop the rest of this text that describes what is reset. I would suggest adding that if a client has received an ACK frame thus far from the server, it MAY use the RTT sample to seed the new connection's RTT estimator.

-- 
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/493#pullrequestreview-36910584

---

From: Martin Thomson <[email-masked]>
Date: Mon, 08 May 2017 18:13:54 -0700

I considered suggesting that, but there is value in retaining the RTT and you really have to retain crypto state for the Stateless Retry.  I think that it is better to only reset stream 0 offset and packet numbers.

-- 
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/493#discussion_r115389583

---

From: Martin Thomson <[email-masked]>
Date: Mon, 08 May 2017 18:15:23 -0700

+

See, I think that you are getting into telling *implementations* what to do.  A complete reset isn't necessary for interop; only those things that are listed are reset.  Let's save the MUSTs for things that matter.

-- 
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/493#discussion_r115389712

---

From: janaiyengar <[email-masked]>
Date: Mon, 08 May 2017 19:07:16 -0700

+

Fair, perhaps the wording isn't right. How about stating that all transport state MUST be reset, but a sender MAY continue using the RTT estimate.

-- 
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/493#discussion_r115394557

---

From: janaiyengar <[email-masked]>
Date: Mon, 08 May 2017 19:08:01 -0700

Also flow control state needs to be reset.

-- 
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/493#discussion_r115394638

---

From: Martin Thomson <[email-masked]>
Date: Mon, 08 May 2017 19:13:19 -0700

Well, that follows from the reset of the stream offset.

-- 
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/493#discussion_r115395098

---

From: janaiyengar <[email-masked]>
Date: Mon, 08 May 2017 23:00:52 -0700

-Thus, all Client Cleartext packets, 0-RTT Encrypted packets, and Non-Final
-Server Cleartext packets MUST use the client's randomly-generated initial
-Connection ID. Final Server Cleartext packets, 1-RTT Encrypted packets, and all
-short-header packets MUST use the final Connection ID.
+When the server receives a Client Initial packet, it chooses a new value for the
+connection ID and sends that in its response.  The server can send a new
+connection ID in any packet that is sent in response to a Client Initial packet.

nit: The server can --> The server MUST

-- 
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/493#pullrequestreview-36945864

---

From: Martin Thomson <[email-masked]>
Date: Tue, 09 May 2017 00:06:32 -0700

@martinthomson pushed 1 commit.

68f7f04  MUST MUST MUST

-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/quicwg/base-drafts/pull/493/files/93d4eaa2178ba9c8debf9bc23528e34c241fc844..68f7f04b0e728699b20e3f76469f62cc799f69c0

---

From: janaiyengar <[email-masked]>
Date: Tue, 09 May 2017 17:16:31 -0700

Not for connection-level flow control. I really think the spec should say reset transport state and then suggest that it MAY carry over RTT information. Is there anything else that you want carried over?

-- 
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/493#discussion_r115631367

---

From: janaiyengar <[email-masked]>
Date: Tue, 09 May 2017 17:42:52 -0700

I think it would be clearer to simply think of transport state, including connection ID, as being entirely reset or restarted after a VN/SR, and for the server to simply state that no connection state is stored when a VN/SR packet is sent. I've left a few comments inline.

> +## Stateless Retries {#stateless-retry}
+
+A server can process an initial cryptographic handshake messages from a client
+without committing any state.  This allows a server to perform address

I think it's adequate to say that no connection state needs to be maintained after sending a Stateless Retry... I don't think it's necessary to discuss accounting of data on stream 0 here.

> @@ -1131,7 +1219,34 @@ version negotiation occurred but it would have selected a different version

+A server can process an initial cryptographic handshake messages from a client
+without committing any state.  This allows a server to perform address

It causes the client to reset transport state, not just stream 0.

This is still confusing to me. It's not clear to me why there's even a discussion of what the server does not have to remember. Stateless Retry is a shoot and forget packet, that should be described as "no state is maintained for the received client packet," which should be adequate, I think. Here's what I'm imagining for this section:

## Stateless Retries {#stateless-retry}

A server can process an initial cryptographic handshake messages from a client without committing any state.  This allows a server to perform address validation ({{address-validation}}, or to defer connection establishment costs.

A server that generates a response to an initial packet without retaining connection state MUST use the Server Stateless Retry packet ({{packet-server-stateless}}).  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 Server Stateless 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 Server Stateless Retry packet type is used to carry the HelloRetryRequest message.

-- 
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/493#pullrequestreview-37188201

---

From: Martin Thomson <[email-masked]>
Date: Tue, 09 May 2017 19:03:17 -0700

Yes, that also.  The consumed max data is the sum of stream maximum offsets.

-- 
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/493#discussion_r115641339

---

From: Martin Thomson <[email-masked]>
Date: Tue, 09 May 2017 21:07:48 -0700

84410a7  Describe stateless retry in terms of a transport reset

-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/quicwg/base-drafts/pull/493/files/68f7f04b0e728699b20e3f76469f62cc799f69c0..84410a748fd4597ab827e568b578f2e7f6356eb7

---

From: Martin Thomson <[email-masked]>
Date: Tue, 09 May 2017 23:04:48 -0700

The latest takes Jana's suggestions.  It's a wash either way.

-- 
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/493#issuecomment-300383354

---

From: janaiyengar <[email-masked]>
Date: Wed, 10 May 2017 16:32:29 -0700

janaiyengar approved this pull request.

-- 
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/493#pullrequestreview-37454685

---

From: janaiyengar <[email-masked]>
Date: Wed, 10 May 2017 16:35:57 -0700

Thanks much for accepting my suggestions! The text is clearer, at least to me. 

-- 
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/493#pullrequestreview-37455146

---

From: Martin Thomson <[email-masked]>
Date: Wed, 10 May 2017 17:20:29 -0700

Merged #493.

-- 
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/493#event-1077399824