Subject: [TLS] ECH and resumption - what to put in SNI?

From: Stephen Farrell <[email-masked]>
Date: Fri, 25 Jun 2021 15:21:09 +0100

Hiya,

If a client established a session to foo.example.com
using ECH with a public_name of example.com, what ought
the client put in the SNI when resuming?

Ignoring ECH, 8446 seems to imply one ought put in
foo.example.com [1] but that'd defeat the purpose of
ECH.

If one omits SNI, that would likely be hard to handle
for a client-facing server when it tries to route
to a good split-mode backend. The same could be true
even if example.com is included as the SNI.

I guess the client could do ECH again, but that'd also
be odd, as it'd require asymmetric crypto when resuming
(which I guess is a lot of the point of tickets), and
depending on ticket ages vs. ECHConfig key rotation
times, might cause interesting failures for a library
client that can't do fresh DNS queries from within the
library (and might never see the TTL of the HTTPS/SVCB
RR in any case).

Am I missing something obvious? If not, what's best here?
(And we should probably have some text in the draft on
this too.)

Cheers,
S.

PS: I guess if the inner and outer ALPNs differed in
the original CH, similar issues might arise for a
client-facing server, in terms of figuring out the
right backend to which the resumed session should be
routed, if routing were based on e.g. the inner ALPN.

[1] https://datatracker.ietf.org/doc/html/rfc8446#page-57

---

From: Ben Schwartz <[email-masked]>
Date: Fri, 25 Jun 2021 10:36:54 -0400

> the client put in the SNI when resuming?
...

> I guess the client could do ECH again

That's my expectation.

...

> might cause interesting failures for a library

I expect the application would pass an ECHConfigList to the TLS library
with each new connection request, and new requests might be resumed from a
ticket cache.  The TLS library doesn't need to know anything about the TTL,
because the ECHConfigList is single-use, and independent from whether the
resumption cache was used.

---

From: Eric Rescorla <[email-masked]>
Date: Fri, 25 Jun 2021 07:38:53 -0700

> library (and might never see the TTL of the HTTPS/SVCB

TLS session resumption is soft state, so I believe the correct response
here is to send ECH. Otherwise, the server cannot properly respond
if it is not willing to accept the ticket.

The only real alternative here is to have some way for the server
to indicate that it has forgotten the ticket and the client needs to
do a full handshake and *now* do ECH. But of course, that's
not something that's currently specified and isn't really a great
fit for anything in the protocol, though I guess HRR is closest.

-Ekr

> _______________________________________________
> TLS mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/tls
>

---

From: David Benjamin <[email-masked]>
Date: Fri, 25 Jun 2021 12:01:11 -0400

In addition to needing to send ECH in case the server declines resumption,
we need to keep the ticket under encryption anyway. Without changing how
resumption works, there are a couple of attacks on cleartext tickets:

1. If the tickets from two backend servers are distinguishable from each
other, a cleartext ticket will tell you which backend server it was. This
isn't that implausible as ticket formats often start with a "key name" to
handle ticket rotations (RFC5077 even recommended this), and different
backend servers will use different key names if they don't intentionally
coordinate them.

2. Even if the backend servers have aligned their tickets, an attacker can
still check if the server believes a ticket is resumable with a server name
by sending a non-ECH ClientHello, copying the ticket, making up a fake
binder, and seeing if the server noticed the binder was bad. (Bad binders
are fatal to the connection, but the server only checks a binder once it's
decided to resume with a ticket.) This allows an attacker to confirm a
guess about the server name, up to ticket scope granularity.

Always sending ECH avoids both of these.

This is also the simplest answer and aligns with how we've done everything
else in TLS. The client always offers everything it accepts and allows for
resumption to miss. Resumption may miss for reasons other than key
rotation. Suppose the server changed its version or cipher suite
preferences. That would impact which tickets it accepts. Plus RFC8446
requires that the client resume with the same SNI value, and we have
draft-ietf-tls-cross-sni-resumption as a WG item. Making SNI implicit from
resumption would require revisiting all of that.

I don't follow the concern about clients that can't do fresh DNS queries.
There are two possibilities for any given layer of the system that sets up
TLS:

1. Either this layer knows how to set up TLS, but doesn't know how to
establish connections. Low-level TLS APIs look like this. This layer must
take both the transport connection and ECHConfigList as an external
parameter. Resumption works orthogonally: the layers above run through the
same connection establishment procedure independent of resumption, so you
won't have any more stale of ECHConfigList for resumption as full
handshake. If this layer doesn't know how to establish connections for full
handshakes, it doesn't know how to do it for resumption handshakes either.

2. Or this layer knows how to establish a connection *and* set up TLS.
Maybe this is a higher-level TLS API. Maybe this is the
MakeHTTPSConnection() portion of your HTTP stack. In this case, the layer
is responsible for DNS lookup, evaluating HTTPS/SVCB queries, and using the
ECHConfigList. Resumption is equally orthogonal: whenever you make a
connection, you do the DNS lookup, possibly using a cached record. Then you
check your session cache. Use ECH if you have an ECHConfigList. Offer
resumption if you have a session. Do both if you have both.

In both cases, resumption doesn't affect ECHConfigList availability.

---

From: Stephen Farrell <[email-masked]>
Date: Sat, 26 Jun 2021 01:45:30 +0100

So I guess we're landing on "if the client got a ticket via
a session that successfully used ECH, it MUST send a fresh
ECH when using that ticket"? That's ok I guess, but maybe
some more detail is needed...

On 25/06/2021 17:01, David Benjamin wrote:
> 2. Or this layer knows how to establish a connection*and*  set up TLS.

I'm not sure yet that OpenSSL matches either 1 or 2, (I've
only done some basic tests) but in any case it seems like
the client could have a ticket cached but get an entirely
different SVCB RR with a different public_name the 2nd time
so I'm not sure that things work well in all cases.

S.

---

From: David Benjamin <[email-masked]>
Date: Fri, 25 Jun 2021 22:24:17 -0400

> so I'm not sure that things work well in all cases.

The main uses of OpenSSL are (1). TLS stacks typically will be (1) because
connection establishment has all kinds of application-specific bits. E.g.
connection establishment in general needs to integrate with proxy logic for
HTTP CONNECT proxies, and interpreting the HTTPS/SVCB record needs to
integrate with Alt-Svc, and deciding between TCP and QUIC.

There's some stuff that's partially shaped like (2) with connect BIOs and
such, but most applications don't use it. I've not thought very hard about
how an HTTPS/SVCB embedding of that API would look like. But either way,
the point about resumption being orthogonal stands.

David