Subject: [quicwg/base-drafts] Describe a new version negotiation mechanism which allows for (#1755)

From: ekr <[email-masked]>
Date: Mon, 17 Sep 2018 09:01:41 -0700

no-cost negotiation as long as the client and server support
a common version. It also removes a lot of text.
You can view, comment on, or merge this pull request online at:

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

-- Commit Summary --

  * Describe a new version negotiation mechanism which allows for

-- File Changes --

    M draft-ietf-quic-transport.md (120)

-- Patch Links --

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

---

From: ianswett <[email-masked]>
Date: Mon, 17 Sep 2018 16:15:16 +0000 (UTC)

ianswett commented on this pull request.

I like the approach, though I want to read it a few more times to make sure nothing from the old text is lost.
1) Should there be an issue for this?  2) Should this be discussed in NY?

-- 
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/1755#pullrequestreview-156004427

---

From: ekr <[email-masked]>
Date: Mon, 17 Sep 2018 10:23:18 -0700

@ianswett: yes, we should discuss in NY.

I will defer to the chairs for the need for an issue.

-- 
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/1755#issuecomment-422100002

---

From: Kazuho Oku <[email-masked]>
Date: Mon, 17 Sep 2018 17:42:27 +0000 (UTC)

Am I correct in assuming that resumption will be forbidden when the proposed mechanism is used?

I ask this because if we forbid that, the only things that need to be processed in a different version becomes the Initial packet and the CRYPTO 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/1755#issuecomment-422106638

---

From: ekr <[email-masked]>
Date: Mon, 17 Sep 2018 11:55:56 -0700

@kazuho: I would think the client would be allowed to resume but the server would have to reject resumption/0-RTT if it changed version

-- 
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/1755#issuecomment-422130084

---

From: Ryan Hamilton <[email-masked]>
Date: Mon, 17 Sep 2018 19:24:15 +0000 (UTC)

I think an issue for this would be a good idea.

I'm not sure that I understand what constraints on the two versions are required in order to allow this approach to work. Consider the case where only two versions are supported, A and B. The client sends an INITIAL packet containing the ClientHello (or the like) encoded with A, but indicates that it also supports B. The server and client both prefer B, so the server decide to upgrade to B. Are we guaranteed that everything needed for B will be in the A ClientHello? Could the TLS handshake mapping change between A and B is some way that would cause problems here? What about 0-RTT data? What if between A and B we changed the stream mapping / numbering? The client would have created (and sent) streams allocated with the logic of A but which would be incorrect for B? It seems really hard to guarantee that there are no such changes between A and B.

I think there are simpler solutions to the problem this PR intends to solve:
1) Advertise supported versions. For the HTTP/QUIC use case, Alt-Svc already gives us a mechanism to advertise QUIC versions so we're not in a position where the client doesn't know the server's versions.
2) Use two connections. Start a connection with versions A and send 0-RTT streams. When the client learns that the server supports a preferred version, it should start a new connection using version B, but not send new requests on this connection until/unless the handshake completes. Once that happens, the client should send new requests on B and close A once it become idle. This avoids waiting an RTT to learn about the new version and avoids the complexity of trying to upgrade an existing connection from one version to another.

-- 
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/1755#issuecomment-422138882

---

From: Kazuho Oku <[email-masked]>
Date: Mon, 17 Sep 2018 13:14:23 -0700

@ekr 
> @kazuho: I would think the client would be allowed to resume but the server would have to reject resumption/0-RTT if it changed version

Thank you for the clarification. Makes sense to me.

I like the idea behind the PR; to open the possibility of future versions of QUIC accepting v1 Initial packets without spending extra round-trip. Current approach does not allow that, and that will hinder us from  introducing v2.

-- 
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/1755#issuecomment-422154605

---

From: Kazuho Oku <[email-masked]>
Date: Mon, 17 Sep 2018 21:15:13 +0000 (UTC)

@RyanAtGoogle 
> I'm not sure that I understand what constraints on the two versions are required in order to allow this approach to work.

FWIW, my assumption is that the only constraint would be that the TLS protocol version needs to be compatible.

Consider the case where you want to send a QUICv1 Initial packet that can be upgraded to v3. From the Initial packet, the v3 server needs to extract the initial flight of the TLS handshake (i.e. ClientHello) and the elements that would have existed in the v3's Initial packet. It is obvious that the TLS handshake transcript can be extracted. The other elements can be transmitted as a TLS ClientHello extension.

-- 
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/1755#issuecomment-422174161

---

From: Martin Thomson <[email-masked]>
Date: Mon, 17 Sep 2018 14:30:08 -0700

martinthomson commented on this pull request.

> @@ -1338,9 +1338,29 @@ Servers MUST drop incoming packets under all other circumstances.
 ## Version Negotiation
 
 Version negotiation ensures that client and server agree to a QUIC version
-that is mutually supported. A server sends a Version Negotiation packet in
-response to each packet that might initiate a new connection, see
-{{packet-handling}} for details.
+that is mutually supported. The client's Initial packet contains two version
+indications:
+
+* A packet version which indicates which version it has been encoded
+  with. This SHOULD be a version which the client expects most servers
+  to support (most likely the oldest common version).
+  
+* A list of versions which the client supports in the
+  "supported_versions" transport parameter).

trailing paren

> @@ -1338,9 +1338,29 @@ Servers MUST drop incoming packets under all other circumstances.
 ## Version Negotiation
 
 Version negotiation ensures that client and server agree to a QUIC version
-that is mutually supported. A server sends a Version Negotiation packet in
-response to each packet that might initiate a new connection, see
-{{packet-handling}} for details.
+that is mutually supported. The client's Initial packet contains two version
+indications:
+
+* A packet version which indicates which version it has been encoded
+  with. This SHOULD be a version which the client expects most servers
+  to support (most likely the oldest common version).

I'd drop the parenthetical here.

> -response to each packet that might initiate a new connection, see
-{{packet-handling}} for details.
+that is mutually supported. The client's Initial packet contains two version
+indications:
+
+* A packet version which indicates which version it has been encoded
+  with. This SHOULD be a version which the client expects most servers
+  to support (most likely the oldest common version).
+  
+* A list of versions which the client supports in the
+  "supported_versions" transport parameter).
+
+If the server understands the packet version -- even if it is not its
+most preferred version -- then it deprotects the packet and selects
+the most preferred version out of the client's supported versions
+list, and responds with that version. This allows a client and server

Aside from sentence construction here, which needs work, I don't understand how you believe this should work.  If you believe that a server can continue a connection, how can it continue from an Initial taken from a different version?

-- 
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/1755#pullrequestreview-156123951

---

From: Mike Bishop <[email-masked]>
Date: Wed, 19 Sep 2018 17:06:47 +0000 (UTC)

I'm not strongly opposed to this as an optimization, but it doesn't feel necessary for QUICv1.  You remove a lot of text, but it's adding a second layer of version negotiation -- I would expect that it needs more text, and I'm not convinced the text you removed is obsoleted by adding a second way to negotiate.

-- 
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/1755#issuecomment-422882041

---

From: Martin Thomson <[email-masked]>
Date: Thu, 20 Sep 2018 13:16:12 -0700

The big loser here is the validation of version negotiation.  I think that most of that is stuff we want to lose.  By having all the client's supported versions available to the server we lose a lot of the complication that the text was addressing.  I think that we do need new text to describe the properties we are looking to obtain and how we obtain them, but that should be short.  It appears as though the proposed text is a little too lean (the rationale for having transport parameter format stability is gone, for instance).

-- 
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/1755#issuecomment-423318212

---

From: Kazuho Oku <[email-masked]>
Date: Wed, 26 Sep 2018 21:37:53 -0700

> The big loser here is the validation of version negotiation. I think that most of that is stuff we want to lose. By having all the client's supported versions available to the server we lose a lot of the complication that the text was addressing.

IIUC, the risk here is that if we have a client and server that support both QUIC v1 and vX (a future version of QUIC that does not use TLS), we cannot detect downgrade attack that forces the peers to use v1 instead of vX.

Are we fine with that?

If not, I might prefer retaining the current approach in v1 _and_ consider introducing the proposed approach in v2 (my understanding is that this type of version negotiation can be introduced afterwards, like we introduced supported_versions in TLS 1.3).

-- 
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/1755#issuecomment-424956589

---

From: MikkelFJ <[email-masked]>
Date: Wed, 26 Sep 2018 23:51:34 -0700

Any risk of a downgrade attack sounds like a big loose. Especially if the only concern is to save a few messages during a few hours of deployment of a new server. Otherwise, if it can be done safely, by all means...

The IoT scenario is very real. For example, the author of the new BearSSL is concerned about the cost of TLS 1.3 on constrained devices and believe TLS 1.2 will live on. This will consequently lead to a different version of QUIC for such devices, if he is right.

-- 
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/1755#issuecomment-424978444

---

From: ianswett <[email-masked]>
Date: Thu, 27 Sep 2018 06:28:25 -0700

Kazuho, I think this approach only works if the server supports both the version the client tries intitially and another version the client offers.

The client can choose to only offer alternate versions it prefers, but does not know if the server supports.  I believe that mitigates the downgrade attack?  If the client tries v1 and the server only supports v0, the server is going to have to send a VN anyway I think?

-- 
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/1755#issuecomment-425092040

---

From: Kazuho Oku <[email-masked]>
Date: Thu, 27 Sep 2018 21:21:38 -0700

@ianswett The case I am concerned is like below.

Client and server supports both v1 and vX.

Client prefers using vX, and sends Initial using vX format. Middlebox intercepts that, and injects a Retry  that only allows v1. In response, client sends Initial using v1 format. TP will still include v1 and vX.

Now the server sees that the client supports both v1 and vX, but does not have a clue that the client _preferred_ using vX. Hence the handshake succeeds using v1. At this point, downgrade attack succeeds.

The key observation here is that it is only the client that knows what the initially tried version is. Therefore, we currently require the client to verify if there has been an attempt to downgrade. The proposed change removes that requirement without a replacement.

If we want to let the server select the version, I think that we should require the client to send it's original version number using TP so that the server can determine if there was a downgrade attack.

-- 
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/1755#issuecomment-425316849

---

From: ianswett <[email-masked]>
Date: Fri, 28 Sep 2018 03:39:08 -0700

nit: Above, you meant the middlebox injects a VN, not Retry, correct?

We could force the client to list the initially chosen version first or last as well, if we don't want another transport parameter.

My thinking was the client would only list other versions it likes as well or better than the version it initially tried.  ie: it'd try 1, but also list 2.

In my mind, the question of timing comes down to whether we think this will be helpful to upgrade from draft IETF versions to the 'final' v1 .  I'd like to think the frames are not likely to change prior to v1 so that feature won't need to be exercised, but that's probably wishful thinking.

-- 
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/1755#issuecomment-425396216

---

From: Mike Bishop <[email-masked]>
Date: Fri, 28 Sep 2018 09:30:39 -0700

I think we don't want to remove the client's initially-offered version or the server's list of other supported versions -- they're there for valid reasons and are still needed.  The client's original version is used for the server to ensure that the VN wasn't spurious.  The server's other supported versions are useful for the client to remember and pick a more-preferred version next time.

This optimization should strictly add to the VN information in the handshake, with a list of compatible version the server could switch to in its response.

(The suggestion that such compatible versions would include near-final draft versions and the final RFC is definitely intriguing from a deployment standpoint, incidentally.)

-- 
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/1755#issuecomment-425492193

---

From: Mike Bishop <[email-masked]>
Date: Fri, 28 Sep 2018 16:32:32 +0000 (UTC)

MikeBishop commented on this pull request.

> @@ -1773,75 +1793,9 @@ a transport parameter therefore disables any optional protocol feature that is
 negotiated using the parameter.
 
 New transport parameters can be registered according to the rules in
-{{iana-transport-parameters}}.
-
-
-### Version Negotiation Validation {#version-validation}

Build failure is because you've removed this section without updating the other places in the draft that reference it.  (Incidentally, the pre-commit hooks should have blocked you from committing something that doesn't build -- can you run `make update` to make sure that's installed?)

-- 
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/1755#pullrequestreview-159934736

---

From: MikkelFJ <[email-masked]>
Date: Fri, 28 Sep 2018 09:33:32 -0700

Guidelines on how to decide which version is preferable? Is that a local configuration? Or list order in TP? An IoT device might be able to speak all versions, but have vastly different preferences from a high powered 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/1755#issuecomment-425493038

---

From: Mike Bishop <[email-masked]>
Date: Fri, 28 Sep 2018 09:39:41 -0700

I think preference is always in the hands of the one who switches, with ability to constrain options on the other party.  So I'd frame it as:
- Client begins with the version it thinks is most likely to be supported
- Includes a list of compatible versions it considers equally-or-more preferred
- Server either chooses the most preferred from the set of (used, offered), or sends VN if there's no overlap
- Client learns from VN or the transport parameters the set of versions the server is offering; if it sees something it likes better, it remembers to offer that in the future.

There's not necessarily an obligation to disclose every version you're capable of speaking; you might only disclose the ones you want a peer to use.

-- 
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/1755#issuecomment-425494736

---

From: Martin Thomson <[email-masked]>
Date: Fri, 28 Sep 2018 11:15:30 -0700

> If we want to let the server select the version, I think that we should require the client to send it's original version number using TP so that the server can determine if there was a downgrade at…

This does.  The client lists all its supported versions.  We can - as is customary - insist that the client puts its preferences first.  But a consequence of this design is that the server ultimately decides which version is used.

-- 
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/1755#issuecomment-425522513

---

From: Kazuho Oku <[email-masked]>
Date: Fri, 28 Sep 2018 13:48:01 -0700

@ianswett 
> nit: Above, you meant the middlebox injects a VN, not Retry, correct?

Yes. Thank you for noticing that.

> My thinking was the client would only list other versions it likes as well or better than the version it initially tried. ie: it'd try 1, but also list 2.

That's certainly an option, but then you cannot detect downgrade attacks that happen between the wire-compatible versions too.

IMO, it is beneficial to define two version negotiation mechanisms (i.e. one uses VN and one uses the proposed method) as independent as possible, and that leads me to think that the client should include all the versions it can use in the TP, regardless of what the interaction using VN was.

> In my mind, the question of timing comes down to whether we think this will be helpful to upgrade from draft IETF versions to the 'final' v1 . I'd like to think the frames are not likely to change…

That makes sense. Thank you for pointing that out.

-- 
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/1755#issuecomment-425561377

---

From: martinduke <[email-masked]>
Date: Fri, 28 Sep 2018 14:28:59 -0700

This is an interesting idea, but it also strikes me as the kind of minor optimization that shouldn't make the cut at this stage in the process. I understand @kazuho 's point that it might ease v2 transition, but the VN code has been stable for a long time and there are lots of things to think about here.

This also puts version choice in the hands of the server, rather than client. I'm not sure how I feel about that. If clients are picking a version based on their resource constraints, then this is a bad 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/1755#issuecomment-425571334

---

From: Kazuho Oku <[email-masked]>
Date: Fri, 28 Sep 2018 16:30:21 -0700

@martinduke FWIW, my view is that current VN that lets the client detect downgrade attack does not work. I have filed #1810 that explains the issue.

-- 
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/1755#issuecomment-425593497