Subject: Re: Updated Public Reset authentication patch

From: Martin Thomson <[email-masked]>
Date: Wed, 3 May 2017 17:44:08 +1000

Sorry about not getting back to your essay as quickly as I intended.  As ou

On 28 April 2017 at 19:27, Brian Trammell <[email-masked]> wrote:
> So unless I'm missing something here, I'm not sure that "privileging just one path" is a thing that happens.

I was primarily talking about migration.  If you move from one network
to another, the path prior to the migration gets the handshake, the
path after the migration gets the close.  The first is privileged in
the sense that it might see a reset verifier.  And yes, multipath
makes this much more obvious a problem.

> (I'm ignoring multipath here, because in the multipath case, I suspect we'll end up with an MPTCP-like design [...]

(I don't share your assumption about its design; I want a single
cryptographic context, for one.  FWIW, I'm thinking of multipath as
make before break without the break.  That's also why I want to make
any path signals explicitly path-specific.)

>> We can work around that, but it either requires removing packet
>> numbers completely, or greatly enhancing the information exposed to
>> the path.  For instance, if we had a packet number echo the server
>> would be able to pick a plausible packet number for its reset.
>
> ...I wouldn't say we need to greatly enhance it; this PR enhances it enough for the purposes of separating endpoint-generated public resets from spoofed ones...

Note that my PR does not do this.  It would require changes to do so.

> I agree completely that it's desirable to separate the discussions about end-to-end from end-to-path and path-to-end signaling; but public reset, in particular, counfounds that desire, since it's an end-to-end signal that radiates information to the path. We should focus on, and probably work to minimize, these inseparable effects.

Yes, I agree.  Though I'm not as enthusiastic about a design that
makes public reset indistinguishable from other traffic.  We could do
it but the only way I know how to make that work is to force endpoints
to try hashing every packet of a certain size that fails to decrypt.
We could use a key phase change to reduce that to the points at which
we roll keys, so it's not awful, but it's probably also creating some
nasty externalities (e.g., packets of the magic size cause connections
to fail).

> I don't yet see a way to get better-than-economic defense without allowing a path element to authenticate an endpoint, so that it can verify that each header bit carrying a signal indeed came from the endpoint it should have. This is vastly more expencive, and essentially goes down the path of building QUIC atop a multiparty cryptographic protocol -- mcTLS occupies a far corner of this design space. I don't think it's possible to deploy something like this safely in the Internet with the primitives we have available to us, but IANAC.

Nor I, but you are right in observing that it gets funky if you want a
verifiable end-to-middle signal.  One-time passwords like in the
public reset design only work for one bit of information, and I assume
that any generic system here needs to signal more bits, which could
mean public key crypto and I don't think that anyone wants that.
(There's probably something else out there, but nothing I can think of
works for a potentially large audience and arbitrary messages.)

---

From: "Brian Trammell (IETF)" <[email-masked]>
Date: Wed, 3 May 2017 12:06:44 +0200

> On 03 May 2017, at 09:44, Martin Thomson <[email-masked]> wrote:
> 

Ah, understood.

> any path signals explicitly path-specific.)

(Aside: I'm pretty sure we agree on the design here: I intended less by "MPTCP-like" than was taken. :) Single cryptographic context is IMO a no-brainer, as is designing it with similar semantics to make-before-break migration. But let's have that discussion when it comes on charter.)

> Note that my PR does not do this.  It would require changes to do so.

Ah. Yep. Sorry, I carried over some state from PR20 the first time I read this.

> nasty externalities (e.g., packets of the magic size cause connections

Ew.

> works for a potentially large audience and arbitrary messages.)

One could probably design a proof verification to signal one of N (for small N) conditions, of which one would be reset, such that the signaling of a verification would require the production of a new proof for further signaling (by providing for one verification value per condition, all values of which are simple transforms of the bits hashed to create the proof -- verification time scales linearly with the number of possible conditions). This isn't completely generic, but it's better than one bit.

With respect to close/reset*, there's another possibility on the verifiability continuum that we allude to (but don't fully define) in the state machine draft: "cancellable". Here, an endpoint can signal a close, but so can any on-path device that has access to a valid connection ID and packet number. A spoofed close will be detected by the endpoint (since it won't decrypt), which will continue sending traffic on the same n-tuple and connection ID. The presence of continued traffic on the n-tuple is itself a signal that a prior close was spoofed. Spoof cancellation semantics only apply to close signaling, and there are weird corner cases to consider (what about a spoofed close coincident with a real migration? can two collaborating nodes use cancellation to keep legitimate firewall pinholes open for illegitimate purposes? etc.), but this does represent another possible design...

* We still need to clarify what we mean by reset: is this "all connection termination" or "abnormal connection termination" or "unrecoverable connectivity error"?

Cheers,

Brian

---

From: Martin Thomson <[email-masked]>
Date: Wed, 3 May 2017 20:52:14 +1000

> With respect to close/reset*, there's another possibility on the verifiability continuum that we allude to (but don't fully define) in the state machine draft: "cancellable". Here, an endpoint can…

Yes, someone suggested that ICMP unreachable might have this property.

---

From: Christian Huitema <[email-masked]>
Date: Wed, 3 May 2017 07:06:21 -0700

> nasty externalities (e.g., packets of the magic size cause connections
We could do better than "hash every packet" if instead of just sending a
reset verifier the server also sent a reset nonce. The public reset
would then contain something like header|reset-nonce|reset-proof, where
proof = hash(reset-nonce|reset-verifier). Servers with reduced state
could just derive both nonce and verifier from a static secret and the
connection ID. Clients that remember both nonce and verifier would just
check that the nonce matches the preset value before computing the hash,
thus greatly reducing risk of spending CPU cycles on random garbage.

-- Christian Huitema

---

From: Eric Rescorla <[email-masked]>
Date: Wed, 3 May 2017 07:40:58 -0700

> to try hashing every packet of a certain size that fails to decrypt.

It's actually pretty easy. The only reason for the hash preimage trick
is that you want public verifiability.

I'm going to call this "Stateless Reset" to differentiate from "Public
Reset".
Assume the server has a long-term key K (as in the hash design).

In EncryptedExtensions, the client sends V = HKDF(K, <conn-id>).
When the server wants to reset a connection it generates a properly
formatted packet that consists of:

Header || V || <random bytes>

And when the client receives a packet, before trying to decrypt it, it
looks for V as the initial bytes. No hashing required, and it's just
a memcmp.

-Ekr

---

From: Martin Thomson <[email-masked]>
Date: Thu, 4 May 2017 07:56:59 +1000

> In EncryptedExtensions, the client sends V = HKDF(K, <conn-id>).

I think that Christian's idea works well enough.  This one requires an
impossibility :)

---

From: Eric Rescorla <[email-masked]>
Date: Wed, 3 May 2017 14:59:21 -0700

> I think that Christian's idea works well enough.  This one requires an

Why is this an impossibility?

-Ekr

---

From: Martin Thomson <[email-masked]>
Date: Thu, 4 May 2017 08:45:57 +1000

> Why is this an impossibility?

The client doesn't send EncryptedExtensions.  Maybe you meant exactly
what Christian said and the V is sent by the server?

---

From: Eric Rescorla <[email-masked]>
Date: Wed, 3 May 2017 15:47:20 -0700

Yes, I meant the server.

-Ekr

On Wed, May 3, 2017 at 3:45 PM, Martin Thomson <[email-masked]>
wrote:

> > On Wed, May 3, 2017 at 2:56 PM, Martin Thomson <[email-masked]
> >
> > wrote:
> >>

---

From: Martin Duke <[email-masked]>
Date: Thu, 4 May 2017 20:16:58 -0700

I've finally been able to process this thread. This problem has so many
dimensions that we should definitely discuss in Paris.

TL;DR I think signals to middleboxes are important, and I endorse MT's
mechanism but with the proof sent in the clear. I have concerns about how
this might work without connection IDs or with a changing connection ID, if
some of the MAYs and SHOULDs aren't observed, client-generated public
resets, etc. Once we agree on general approach we can interrogate those
issues.

In my opinion, the logic of this signal extends to also doing #353 and
replacing CONNECTION_CLOSE with a public reset.

*************

There are numerous different tradeoffs we discuss above, but reasoning from
first principles about middleboxes may answer all of these questions. I
propose the following assertions:

1. Middleboxes will do stuff to connections that requires state.

2. There will have to be some sort of idle timeout to clean up that state,
because stuff happens.

3. It is desirable to QUIC endpoints that those timeouts be as long as
possible. Premature state teardown will, at the very least, mess up
whatever the middlebox is trying to optimize, and at worst it will break
the connection (e.g. a firewall may not accept packets if it hasn't seen
the Client Hello.)

4. Middlebox vendors and operators will institute longer timeouts if they
have a *reasonable chance* of being gracefully notified of connection close.

5. On-path observers should not be able to generate (spoof) valid public
resets to middleboxes.

>From these points, we should strive to maximize the likelihood of the
middlebox seeing and validating the public reset, but it's OK if it misses
it in certain corner cases. I propose that MT's mechanism, with the proof
sent in the clear and extended to events where Google-QUIC sends
CONNECTION_CLOSE, meets this test. It's true that path changes and path
failure will prevent delivery of this signal. But this is not terribly
different from the balance of events that we see with TCP.

As for an explicit "path close, connection still open" message, I wouldn't
object to this but I don't see it as necessary, nor do I think it likely
that endpoints would bother to send them.

Martin Duke

---

From: Martin Duke <[email-masked]>
Date: Fri, 5 May 2017 10:53:50 -0700

Reading through again, I think what I'm actually arguing for is ekr's PR
#20 instead, since a verifier in the clear is the key distinction between
the two as far as I can tell.

On Thu, May 4, 2017 at 8:16 PM, Martin Duke <[email-masked]> wrote:

> There are numerous different tradeoffs we discuss above, but reasoning
> from first principles about middleboxes may answer all of these questions.
> I propose the following assertions:
>