Subject: [quicwg/base-drafts] A 17 octet connection ID (#1088)

From: Martin Thomson <[email-masked]>
Date: Tue, 30 Jan 2018 23:12:55 -0800

This comes out of the discussion about what it takes to construct a sensible
connection ID for NEW_CONNECTION_ID.  Trying to cram sufficient routing state
into a 64-bit identifier is tricky, especially since that information needs to
be encrypted and probably also authenticated (at least a little).  Using a
block cipher would be ideal, but all the 64-bit ciphers are pretty bad, whereas
all the 128-bit ones are both faster and more available.

The extra 8 bits is for accounting.  If you want to manage key rotation, a key
identifier is helpful.  Having extra space allows for that to be added without
forcing the block cipher to protect less than 128 octets, which can be hard.

The way that packet overheads are managed are different for long and short
headers.  In long headers, the overheads are much higher, but we don't send
many of those, so it's not a big deal.  For short headers, each endpoint sends
a truncate_connection_id transport parameter which sets the length of the
connection ID that will be used in short headers.  Each endpoint sets their own
limit and their peer has to follow this limit.  Anywhere from 0 (no connection
ID) to 17 (all of the connection ID) can be set.

This also closes the discussion about whether connection ID is a number or not.
With truncation, treating it as a number no longer makes sense.

Note that this change shows the corresponding changes to the invariants draft
on the assumption that it will need to be changed at the same time.  We can take
this before adoption, but it will need to be rebased if we do.

Closes #1052, #821, #834, #833, #881.
You can view, comment on, or merge this pull request online at:

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

-- Commit Summary --

  * Make connection ID 136 bits long

-- File Changes --

    M draft-ietf-quic-tls.md (2)
    M draft-ietf-quic-transport.md (205)
    M draft-thomson-quic-invariants.md (41)

-- Patch Links --

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

---

From: Patrick McManus <[email-masked]>
Date: Wed, 31 Jan 2018 08:49:58 -0800

thanks. I think this accurately reflects which way the wind was blowing in Melbourne. The most important property to me, which this reflects, is that the connID is actually a fixed size which might be encoded in shorthand in headers but is still clearly 17 bytes in other contexts.

A couple thoughts: It would be helpful to be explicit about which of the 17 are omitted when being truncated (i.e. the last or low bytes). truncate is probably technically sufficient but explicit is good.

In previous drafts the default was don't omit cid, and now it is do omit cid (i.e. truncate @0).. given that not all environments are robust without some cid, I think our default should be something other than omit completely.

-- 
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/1088#issuecomment-361995066

---

From: MikkelFJ <[email-masked]>
Date: Wed, 31 Jan 2018 08:55:52 -0800

>  It would be helpful to be explicit about which of the 17 are omitted

Yes I think so.

I was thinking perhaps it would be best to have the CID length exposed. Consider a HA-Proxy that does stateful routing. In a future version where it understood QUIC it could be configured to expect a certain CID length so it is not necessary to have it public. But it does complicate configuration and deployment.

Another concern is that a 17 byte CID needs to be hashed if used for state lookup at the client. If there were som assurances of collision resistance on the early bytes it would be simpler to manage.

-- 
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/1088#issuecomment-361997009

---

From: Mike Bishop <[email-masked]>
Date: Wed, 31 Jan 2018 19:29:14 +0000 (UTC)

MikeBishop commented on this pull request.

I like the property that the "real" CID is fixed-size and it gets shortened in certain circumstances.  However, I'm concerned that having no indication of CID presence or length in the short header limits the usefulness of the CID for routing for any network appliance not in explicit cooperation with the server.  That seems like it has the potential to bite us.

>    recipient of a packet to identify the packet protection keys that are used to
   protect the packet.  See {{QUIC-TLS}} for details.
 
 Short Packet Type:
 
-: The remaining 5 bits of octet 0 include one of 32 packet types.
+: The remaining 6 bits of octet 0 include one of 32 packet types.

If you have one more bit, you now have 64 packet types.

>  {: #short-packet-types title="Short Header Packet Types"}
 
-The header form, omit connection ID flag, and connection ID of a short header
-packet are version-independent.  The remaining fields are specific to the
-selected QUIC version.  See {{version-specific}} for details on how packets
-from different versions of QUIC are interpreted.
+The header form and connection ID of a short header packet are
+version-independent.  The remaining fields are specific to the selected QUIC

This makes the Connection ID in the short header a difficult invariant.  There might be one, but there's no way to identify how long it is.  Middleboxes that want to use the CID for routing, unless they're in active collaboration with the server, are kind of stuck.  Which might be intentional, but it seems awkward.

> @@ -682,11 +682,11 @@ sequence of frames, as described in {{frames}}.
 
 ## 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 Omit Connection ID flag.  When present, the Connection ID is in the
-same location in all packet headers, making it straightforward for middleboxes,
-such as load balancers, to locate and use it.
+QUIC connections are identified by their 136-bit Connection ID.  All long

You lower-cased all occurrences of "Connection ID" in this paragraph except this one.

> @@ -682,11 +682,11 @@ sequence of frames, as described in {{frames}}.
 
 ## 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 Omit Connection ID flag.  When present, the Connection ID is in the
-same location in all packet headers, making it straightforward for middleboxes,
-such as load balancers, to locate and use it.
+QUIC connections are identified by their 136-bit Connection ID.  All long
+headers contain a connection ID.  The connection ID is truncated in the short

Since 17 bytes isn't truncated, perhaps "can be" truncated?

> @@ -682,11 +682,11 @@ sequence of frames, as described in {{frames}}.
 
 ## 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 Omit Connection ID flag.  When present, the Connection ID is in the
-same location in all packet headers, making it straightforward for middleboxes,
-such as load balancers, to locate and use it.
+QUIC connections are identified by their 136-bit Connection ID.  All long
+headers contain a connection ID.  The connection ID is truncated in the short
+header, using between 0 and 17 octets.  When present, the connection ID is in
+the same location in all packet headers, making it straightforward for
+middleboxes, such as load balancers, to locate and use it.

Except it's not straightforward; see above.

> @@ -703,6 +703,22 @@ use it for all subsequent Handshake ({{packet-handshake}}) and 1-RTT
 Server's Version Negotiation ({{packet-version}}) and Retry ({{packet-retry}})
 packets MUST use connection ID selected by the client.
 
+A connection ID is truncated when included in short headers.  Each endpoint
+expresses how many octets of the connection ID they require in packets that are
+sent to that endpoint.  The truncate_connection_id transport parameter
+({{transport-parameter-definitions}}) determines the number of octets that are
+included.  An endpoint can request that the connection ID to be omitted entirely
+by setting truncate_connection_id to 0, or include any number of octets up to
+the full connection ID length of 17 octets.  Connection IDs are not truncated
+for any other use.
+
+Note:
+
+: The odd length of the connection ID is chosen to enable efficient construction
+  of the value using 128-bit ciphers with additional space for overhead.
+  Endpoints might negotiate the use of a truncated connection ID for use with
+  the short header.

The second sentence of the note seems pointless, given that you've just talked about this and it's unrelated to the first sentence in the note.

-* the location and size of the Connection ID field in both header forms,
+* the location of the Connection ID field in short headers,

Perhaps worth re-emphasizing that the size is not invariant?

> @@ -1462,13 +1479,13 @@ connection if the integrity check fails with a PROTOCOL_VIOLATION error code.
 
 ## Connection Migration {#migration}
 
-QUIC connections are identified by their 64-bit Connection ID.  QUIC's
-consistent connection ID allows connections to survive changes to the client's
-IP and/or port, such as those caused by client or server migrating to a new
-network.  Connection migration allows a client to retain any shared state with a
-connection when they move networks.  This includes state that can be hard to
-recover such as outstanding requests, which might otherwise be lost with no easy
-way to retry them.
+QUIC connections are identified by their 136-bit Connection ID or whatever part

Along the lines of being explicit about which side we're truncating, maybe call this a "prefix" rather than a "part"?

> +
+Ensuring that the server sends the correct connection ID in its stateless reset
+presents an additional challenge.  Truncation of the connection ID in packets
+that use the short header means that the entire connection ID might not be
+present in the packet that triggers the stateless reset.  Furthermore, the
+server cannot know how many octets from the connection ID that the client
+requested be included in the short header.
+
+A server is expected to have a minimum number of octets that are needed for
+correct routing.  Thus, the server can always know that at least this many
+octets of the packet it receives contain a connection ID.
+
+If the server uses a longer connection ID than the client, there is the
+potential for the additional octets to be used to reveal that the stateless
+reset is not a regular packet.  This is not a serious issue, as it is already
+possible to use other fields to distinguish them from other packet.

Really?  I thought we'd been able to stick to that goal so far.

> +octets of the packet it receives contain a connection ID.
+
+If the server uses a longer connection ID than the client, there is the
+potential for the additional octets to be used to reveal that the stateless
+reset is not a regular packet.  This is not a serious issue, as it is already
+possible to use other fields to distinguish them from other packet.
+
+If a client requires more octets of the connection ID for routing than the
+server requires, those octets will not appear in the packet that the server
+receives.  In this case, the stateless reset might not reach the client.
+
+A server can avoid this by ensuring that it always receives a connection ID that
+is equal to or longer than the connection ID requested by the client.  In
+choosing a connection ID, the server already knows the client's preferred
+transaction ID length, and so can request that the client provide a similarly
+long connection ID.

This is probably the right choice, but again departs from our current semantics that servers don't have to look at the client's transport params before generating their own.

> +If the server uses a longer connection ID than the client, there is the
+potential for the additional octets to be used to reveal that the stateless
+reset is not a regular packet.  This is not a serious issue, as it is already
+possible to use other fields to distinguish them from other packet.
+
+If a client requires more octets of the connection ID for routing than the
+server requires, those octets will not appear in the packet that the server
+receives.  In this case, the stateless reset might not reach the client.
+
+A server can avoid this by ensuring that it always receives a connection ID that
+is equal to or longer than the connection ID requested by the client.  In
+choosing a connection ID, the server already knows the client's preferred
+transaction ID length, and so can request that the client provide a similarly
+long connection ID.
+
+A server can construct the connection ID such that it includes a record the

"a record of", or "an indicator of"

-- 
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/1088#pullrequestreview-93046451

---

From: Martin Thomson <[email-masked]>
Date: Wed, 31 Jan 2018 23:00:47 +0000 (UTC)

martinthomson commented on this pull request.

I guess we have.  Assuming that we do packet number encryption.  Right now the packet number leaks quite a lot of information.

+

Yeah, but this is still a degree shy of making it a negotiation.

 

Removed that bit.  (I don't like making value judgments in specifications anyway.)

I think that the purpose of the connection ID is for cooperating intermediaries, not random middleboxen.  I'm sure that others will disagree, as we're seeing with the proposal to encrypt 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/1088#discussion_r165214281

---

From: Martin Thomson <[email-masked]>
Date: Wed, 31 Jan 2018 23:01:08 +0000 (UTC)

@martinthomson pushed 1 commit.

9c2ebd7  Editorial fixes suggested by @MikeBishop

-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/quicwg/base-drafts/pull/1088/files/c4488213298d73ee6e6c318a6a75711b5f6fca4f..9c2ebd7be052edd567ee8baf301e48f4057ef31b

---

From: Martin Thomson <[email-masked]>
Date: Wed, 31 Jan 2018 15:03:42 -0800

> In previous drafts the default was don't omit cid, and now it is do omit cid (i.e. truncate @0).. given that not all environments are robust without some cid, I think our default should be somethin…

There are really only two values you can default to without making some sort of judgment about what sort of environment gets preferential treatment: 0 or 17.  I don't think that 17 is a great choice.  I would rather force the inclusion of the transport parameter in the common case than decide that 8 is the best number.

-- 
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/1088#issuecomment-362100779

---

From: Mike Bishop <[email-masked]>
Date: Wed, 31 Jan 2018 23:32:13 +0000 (UTC)

A few more.

> @@ -682,11 +682,10 @@ sequence of frames, as described in {{frames}}.

-QUIC connections are identified by their 136-bit Connection ID.  All long
-headers contain a connection ID.  The connection ID is truncated in the short
+QUIC connections are identified by their 136-bit connection ID.  All long
+headers contain a connection ID.  The connection ID can truncated in the short

can => can be

> @@ -890,18 +890,19 @@ Packets that can be associated with an existing connection are handled according
 to the current state of that connection.  Packets are associated with existing
 connections using connection ID if it is present; this might include connection
 IDs that were advertised using NEW_CONNECTION_ID ({{frame-new-connection-id}}).
-Long-form packets for connections with incomplete cryptographic handshakes and
-short-form packets that have a zero-length connection ID are associated with an
-existing connection using the tuple of source and destination IP addresses and
-ports.
-
-A packet that uses the short header could be associated with an existing
-connection with an incomplete cryptographic handshake.  Such a packet could be a
-valid packet that has been reordered with respect to the long-form packets that
-will complete the cryptographic handshake.  This might happen after the final
-set of cryptographic handshake messages from either peer.  These packets are
-expected to be correlated with a connection using the tuple of IP addresses and
-ports.  Packets that might be reordered in this fashion SHOULD be buffered in
+For connections with incomplete cryptographic handshakes packets with the long

Probably want a comma after "handshakes"

-- 
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/1088#pullrequestreview-93122820

---

From: Martin Thomson <[email-masked]>
Date: Thu, 01 Feb 2018 00:01:30 +0000 (UTC)

58c859c  My editor is doing a great job.  Me, less so.

-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/quicwg/base-drafts/pull/1088/files/9c2ebd7be052edd567ee8baf301e48f4057ef31b..58c859c13d21a3ec20004ea6baf45deb14edf65f

---

From: Patrick McManus <[email-masked]>
Date: Wed, 31 Jan 2018 17:19:36 -0800

>  I would rather force the inclusion of the transport parameter in the common case 

seems reasonable

-- 
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/1088#issuecomment-362126648

---

From: janaiyengar <[email-masked]>
Date: Wed, 31 Jan 2018 18:15:09 -0800

janaiyengar requested changes on this pull request.

I think there's some concern that the connection ID ought to be self-describing. One concern, that I'm slightly sympathetic to, is that you'd still have to configure a co-operating middlebox to align with server policy, which may not be easy to do in all server deployments.  I'd recommend leaving this particular question -- of removing the C bit -- out and discuss on an issue instead. The change to 17 byte CIDs and truncation seem quite independent of this question.

-: The omit connection identifier parameter indicates that packets sent to the
-  endpoint that advertises this parameter MAY omit the connection ID in packets
-  using short header format.  This can be used by an endpoint where it knows
-  that source and destination IP address and port are sufficient for it to
-  identify a connection.  This parameter is zero length.  Absence of this
-  parameter means that the connection ID MUST be present in every packet sent to
-  this endpoint.
+: An 8-bit unsigned integer that indicates the length of the connection ID that
+  is to be put in packets that use the short header ({{short-header}}) that are
+  sent to this endpoint.  Values between 0 and 17 inclusive are valid; larger
+  values MUST be treated as a connection error of type
+  TRANSPORT_PARAMETER_ERROR.  This parameter is set to 0 if the transport
+  parameter is omitted, meaning that packets with short headers that are sent to

I think you meant to say Connection ID here: "This parameter is set to 0 if the transport parameter is omitted". 

I'm not sure I like the rest of the phrasing, so how about "This parameter is set to 0 if the connection ID may be omitted in short header packets sent to this endpoint."

How does packet number leak information when there are packet number gaps? Sure, it needs to be fixed so the gaps are asymmetric, but that's basically fixable.

-- 
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/1088#pullrequestreview-93144836

---

From: ekr <[email-masked]>
Date: Wed, 31 Jan 2018 18:51:41 -0800

I don't think this is the right answer. As I mentioned in Melbourne, I believe a better approach is to have the server provide a complete connection ID of variable length and then each side provides exactly that connection ID (or in the case of the server, potentially none at all). Aside from aesthetic considerations, one quite silly side effect of this design is that the client tells the server how to truncate the connection ID without knowing what the server's truncation is, so it's not at all impossible for the server to send you a connection ID where only 8 bytes are meaningful but the client doesn't know that and asks for 12 bytes.

In terms of process, I don't think that this has consensus and I read the minutes as pretty clearly saying that we were going to form a design team to come up with some proposals, and then the WG was going to decide, so this PR seems premature.

-- 
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/1088#issuecomment-362142137

---

From: Martin Thomson <[email-masked]>
Date: Thu, 01 Feb 2018 03:28:31 +0000 (UTC)

That change is integral to the PR.  The bit only makes sense if you intend to send the connection ID on some packets but not others and if you think that an intermediary that is ignorant of the actual length being able to do something meaningful with both sets of 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/1088#discussion_r165252104

---

From: Martin Thomson <[email-masked]>
Date: Wed, 31 Jan 2018 19:30:39 -0800

The construction of a stateless reset requires that the server provide a packet number.  It is probably using a connection ID that it used in the past, so packets can be correlated with previous packets.  The difference in packet numbers is observable.  A server has to pick a random packet number, which likely means a large gap.  That might be used to distinguish a stateless reset.

Packet number encryption fixes that problem.  I think that this will change if we decide to do 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/1088#discussion_r165252317