Subject: [TLS] TLS 1.3 Problem?

From: Michael D'Errico <[email-masked]>
Date: Sun, 27 Sep 2020 15:51:54 -0400

Hi,

Took a quick look at RFC 8446 and noticed that there is no
definition of ServerKeyExchange or ServerHelloDone which
are part of TLS 1.2 and prior.  A 1.3 client talking to a 1.2
or earlier server is likely going to receive both of these
messages:

RFC 5246                          TLS                        August 2008

       Client                                               Server

       ClientHello                  -------->
                                                       ServerHello
                                                      Certificate*
                                                ServerKeyExchange*
                                               CertificateRequest*
                                    <--------      ServerHelloDone
       Certificate*
       ClientKeyExchange
       CertificateVerify*
       [ChangeCipherSpec]
       Finished                     -------->
                                                [ChangeCipherSpec]
                                    <--------             Finished
       Application Data             <------->     Application Data

              Figure 1.  Message flow for a full handshake

Since RFC 8446 obsoletes RFC 5246, this is a serious problem.

How is this supposed to work?   Sorry but I did not follow the
development of TLS 1.3.  I felt that I was unwelcome in this
group by some of the "angry cryptographers" as I call them.

Mike

---

From: Ben Smyth <[email-masked]>
Date: Sun, 27 Sep 2020 22:53:15 +0200

The client will reject the server's ServerHello in your example.

---

From: "Michael D'Errico" <[email-masked]>
Date: Sun, 27 Sep 2020 22:28:43 -0400

> The client will reject the server's ServerHello in your example.

OK, so all eggs in one basket?  I'm afraid to keep reading....

Mike

---

From: Richard Barnes <[email-masked]>
Date: Mon, 28 Sep 2020 00:13:45 -0400

The client is expected to adapt its behavior based on the negotiated
version indicated in the ServerHello.  If the server selects TLS 1.2, for
example, then the client behaves as specified in RFC 5246.  This is no
different from previous version of TLS.

--Richard

On Sun, Sep 27, 2020 at 10:29 PM Michael D'Errico <[email-masked]>
wrote:

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

---

From: "Michael D'Errico" <[email-masked]>
Date: Mon, 28 Sep 2020 00:18:09 -0400

On Sun, Sep 27, 2020, at 22:28, Michael D'Errico wrote:
> 
> I'm afraid to keep reading....

In section 4, HandshakeType and Handshake are missing the
value for the HelloRetryRequest message.

Oh wait, never mind, it's the same value as ServerHello (?).

Everything appears to be a hack within a hack....

If I hadn't already implemented TLS 1.0..1.2 I'd be completely
lost reading RFC 8446.  In fact I AM completely lost reading it.

There's a mention of stateless HelloRetryRequest where the
server sends a "cookie" containing a hash of the ClientHello.
Is it supposed to rely on the client to echo this back?  What
if it doesn't?  Or it puts in a different value?  Or it gets
modified in transit?  Or it sends an initial ClientHello with a
cookie extension as if it got a HelloRetryRequest?  Am I
worried about nothing here?

OK, time for bed....

Mike

---

From: Hannes Tschofenig <[email-masked]>
Date: Mon, 28 Sep 2020 15:07:30 +0000

Hi Mike,

> I felt that I was unwelcome in this group by some of the "angry cryptographers" as I call them.

No reason to worry. Luckily, we don't have any angry cryptographers in this group.

On top of what Richard mentioned in his response, take a look at Appendix D of the spec, see https://tools.ietf.org/html/rfc8446#appendix-D.

Ciao
Hannes

-----Original Message-----
From: TLS <[email-masked]> On Behalf Of Michael D'Errico
Sent: Sunday, September 27, 2020 9:52 PM
To: [email-masked]
Subject: [TLS] TLS 1.3 Problem?

Hi,

Took a quick look at RFC 8446 and noticed that there is no definition of ServerKeyExchange or ServerHelloDone which are part of TLS 1.2 and prior.  A 1.3 client talking to a 1.2 or earlier server is likely going to receive both of these
messages:

RFC 5246                          TLS                        August 2008

       Client                                               Server

       ClientHello                  -------->
                                                       ServerHello
                                                      Certificate*
                                                ServerKeyExchange*
                                               CertificateRequest*

How is this supposed to work?   Sorry but I did not follow the development of TLS 1.3.  I felt that I was unwelcome in this group by some of the "angry cryptographers" as I call them.

Mike

_______________________________________________
TLS mailing list
[email-masked]
https://www.ietf.org/mailman/listinfo/tls
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.

---

From: "Michael D'Errico" <[email-masked]>
Date: Mon, 28 Sep 2020 18:32:26 -0400

On Mon, Sep 28, 2020, at 11:07, Hannes Tschofenig wrote:
> 
> Luckily, we don't have any angry cryptographers in this group.

Were they all pushed away too?

Anyway, back on the topic of stateless HelloRetryRequest, I
don't see how this can work given that the client can make
several modifications to the ClientHello which will invalidate
the hash sent in the "cookie" (even if the client echos it back
as required without modification).

Is stateless HelloRetryRequest even being used?  If so, how?

Mike

---

From: Watson Ladd <[email-masked]>
Date: Mon, 28 Sep 2020 20:38:05 -0400

> as required without modification).

The hash isn't used for validation, but for continuing the running
hash of the transcript to ensure that the negotiation isn't interfered
with. See section 4.4.1.

> Is stateless HelloRetryRequest even being used?  If so, how?

QUIC depends on it iiuc.

Sincerely,
Watson

-- 
Astra mortemque praestare gradatim

---

From: Rob Sayre <[email-masked]>
Date: Mon, 28 Sep 2020 17:51:46 -0700

> Were they all pushed away too?

I don't think this is very likely. The TLS list can get a bit competitive,
but other IETF lists (say, anything related to DNS), are much worse.

thanks,
Rob

---

From: "Martin Thomson" <[email-masked]>
Date: Tue, 29 Sep 2020 12:01:57 +1000

> > Is stateless HelloRetryRequest even being used?  If so, how?

NSS implements HRR this way always.  We pack the necessary state for the connection to continue into the cookie (which is protected with an AEAD).  We can also retain server state, in which case the retained state is compared against the state from the cookie as an extra sanity check.  We chose to do this for a few reasons, but one thing is that it encourages us to use the second ClientHello for negotiating everything.
 
> QUIC depends on it iiuc.

It did, but it doesn't any more.

---

From: Michael D'Errico <[email-masked]>
Date: Tue, 29 Sep 2020 11:14:17 -0400

> NSS implements HRR this way always.  We pack the necessary state for the connection to continue into the cookie (which is protected with an AEAD).  We can also retain server state, in which case th…
OK, so it sounds like you put something similar to a
NewSessionTicket (TLS 1.2) in the cookie with enough
information to recreate the server state.  This is quite
a lot more information than just a "hash" as the spec
implies.

Also, are you sure you want to do this?  The design of
TLS 1.3 was supposed to make it fast, but creating a
pseudo session ticket for every connection requiring a
HRR and then validating and decoding it is going to be
really slow.  And your data center is going to get hotter
because your servers will be compute bound instead of
memory bound (if they even were).

Mike

---

From: Ben Smyth <[email-masked]>
Date: Tue, 29 Sep 2020 17:32:51 +0200

Dear Michael,

On Tue, 29 Sep 2020 at 17:14, Michael D'Errico <[email-masked]> wrote:
> information to recreate the server state.

Whilst getting to grips with TLS 1.3, I wrote a tutorial
(https://arxiv.org/abs/1904.02148), I think you might find it useful.
For instance, I explain the cookie on page 19.

Best regards,

Ben

---

From: [email-masked] (Martin Rex)
Date: Wed, 30 Sep 2020 00:44:23 +0200 (CEST)

> group by some of the "angry cryptographers" as I call them.

The "Obsoletes" Markers used in TLS documents (rfc4346, rfc5246, rfc8446)
are pure crypto-political bullshit, they are completely non-sensical
with respect to the Editorial meaning of "Obsolete:" in the RFC
document series, as it was explained in rfc2223:

   Obsoletes

      To be used to refer to an earlier document that is replaced by
      this document.  This document contains either revised information,
      or else all of the same information plus some new information,
      however extensive or brief that new information is; i.e., this
      document can be used alone, without reference to the older
      document.

IPv6 specification(s) can not possibly obsolete IPv4 specifiation(s)
HTTP/2 spec does not obsolete HTTP/1.1 spec (and does not try to)

Example for *correct* obsoletion:

If you want to implement the Simple Mail Transfer Protocol (SMTP),
it will be sufficient that you only ever read and refer to rfc5321
and _never_ look at rfc2821 nor rfc821 at all -- and still can
expect to your implementation of rfc5321 to interop fine with
older implementations there were created based on rfc821 or rfc2821.

The same is impossible for TLSv1.1 (rfc4346), TLSv1.2 (rfc5246)
and TLSv1.3 (rfc8446). An implementor reading only rfc8446 will
be completely unable to interop with TLSv1.0, TLSv1.1 and TLSv1.2
implementations -- and I am not even sure whether TLSv1.3 can
be implemented with rfc8446 alone and never looking at rfc5246.

-Martin

---

From: "Martin Thomson" <[email-masked]>
Date: Wed, 30 Sep 2020 09:51:27 +1000

> memory bound (if they even were).

It's symmetric crypto[1].  Hardly worth noting.

[1] Mostly.  NSS wraps the symmetric key with an asymmetric key so that server clusters can share session ticket encryption keys without needing interconnects.  But encryption or decryption only happens once per instance.

---

From: Michael D'Errico <[email-masked]>
Date: Tue, 29 Sep 2020 20:30:27 -0400

> [1] Mostly.  NSS wraps the symmetric key with an asymmetric key so that server clusters can share session ticket encryption keys without needing interconnects.  But encryption or decryption only ha…

Well, you also need a MAC, right? (encrypt-then-mac)
This requires another key and a bunch of computation.

Then you have to decode the cookie back into the server
state, and then check whether the new ClientHello (CH)
matches the original from the cookie, with possible
changes, making sure that the key_share supplied in
the new CH was in the original CH, checking that the
list of PSK's was not tampered with in invalid ways, etc.
Much of this is required of any handshake involving HRR
even if not stateless.

Seems worth noting.  Have you measured?

And how do you prevent someone from sending an old
cookie back?  If the server is truly stateless....

Did you (or a client) actually have a data center full of
memory-bound servers which are now handling many
more connections using the stateless HRR feature?

I'm not trying to be unkind, I genuinely don't understand
how stateless HRR can be beneficial.

Mike

---

From: "Michael D'Errico" <[email-masked]>
Date: Wed, 30 Sep 2020 01:11:20 -0400

[I'm resending this with a more appropriate Subject line. --Mike]

Mike

---

From: "Martin Thomson" <[email-masked]>
Date: Wed, 30 Sep 2020 22:17:53 +1000

The costs you describe are trivial. And we limit replay with a binding to remote address, and a short timer. But the benefit is mostly down to reduced code variations. We also implement DTLS where this is properly useful.

---

From: Nico Williams <[email-masked]>
Date: Wed, 30 Sep 2020 11:55:29 -0500

On Wed, Sep 30, 2020 at 10:17:53PM +1000, Martin Thomson wrote:
> The costs you describe are trivial. And we limit replay with a binding
> to remote address, and a short timer. But the benefit is mostly down
> to reduced code variations. We also implement DTLS where this is
> properly useful. 

You need a replay cache system if you're going to allow 0-rtt and the
0-rtt part of the application protocol is sensitive (e.g., it sends
passwords, or missile launch commands).

Replay caches are hard enough to get right when you're clustering
servers.

Nico
--

---

From: Michael D'Errico <[email-masked]>
Date: Wed, 30 Sep 2020 13:20:59 -0400

> The costs you describe are trivial.

The general idea among developers these days that CPU
cycles are free is a huge problem.

You didn't answer my biggest question, though, which was
whether you (or anybody else!) has had success using stateless
HelloRetryRequest to increase the number of connections a
datacenter can handle due to the fact that the servers were
memory-bound.  The amount of memory to hold the first
ClientHello message is trivial.  But if doing stateless HRR has
measurably increased the performance of a data center's web
serving capability, I'll change my mind about it.

 > We also implement DTLS where this is properly useful.

I can't find the DTLS 1.3 spec.  Which RFC is it?

Mike

---

From: <[email-masked]>
Date: Wed, 30 Sep 2020 19:27:39 +0200

Mike, 

DTLS 1.3 can be found here: 
https://tools.ietf.org/html/draft-ietf-tls-dtls13-38

The HRR is used in DTLS 1.3 for DDoS prevention. 

Ciao
Hannes

-----Original Message-----
From: TLS <[email-masked]> On Behalf Of Michael D'Errico
Sent: Wednesday, September 30, 2020 7:21 PM
To: [email-masked]
Subject: Re: [TLS] Is stateless HelloRetryRequest worthwhile? (was Re: TLS 1.3 Problem?)

 > The costs you describe are trivial.

The general idea among developers these days that CPU cycles are free is a huge problem.

You didn't answer my biggest question, though, which was whether you (or anybody else!) has had success using stateless HelloRetryRequest to increase the number of connections a datacenter can handle due to the fact that the servers were memory-bound.  The amount of memory to hold the first ClientHello message is trivial.  But if doing stateless HRR has measurably increased the performance of a data center's web serving capability, I'll change my mind about it.

Mike

---

From: Michael D'Errico <[email-masked]>
Date: Wed, 30 Sep 2020 14:08:52 -0400

> https://tools.ietf.org/html/draft-ietf-tls-dtls13-38

Thank you.

> The HRR is used in DTLS 1.3 for DDoS prevention.

This makes sense since DTLS is over UDP, but TLS
is over TCP, so it's already undergone the SYN/ACK
handshake to establish there's an actual peer with
a reachable address.

I'm thinking that the majority of the time, connections
are going to be legitimate, so optimize for that case.
Keep the first ClientHello in memory, send a simple
unpredictable cookie (maybe 128 bits ?) and just check
that it gets echoed.  Then do all the validation of the
second ClientHello against the first one that you have
to do anyway.

Monitor the activity occurring and if the server decides
it's being attacked in some way, maybe then switch to
stateless HRR (if this makes sense) or do whatever other
countermeasures are appropriate.

Mike

---

From: "Salz, Rich" <[email-masked]>
Date: Wed, 30 Sep 2020 18:20:50 +0000

Not always; see TCP "fast open" options.

---

From: Benjamin Kaduk <[email-masked]>
Date: Wed, 30 Sep 2020 12:50:12 -0700

Hi Mike,

> memory-bound.  The amount of memory to hold the first

Could you say a bit more about why you think that demonstration
of production-grade usage in (non-D) TLS is needed in order to justify
this portion of the specification?  Note that you can use HRR
without cookie just fine.

The HelloRetryRequest message has to exist in TLS 1.3 in order
to cope with the case where the client's optimistic key_share
is not acceptable to the server, and another round-trip is
needed in order to get key shares for the proper group.

Give that there will be an HRR message, it seems/seemed quite
prudent to build out all the bits that DTLS would need from a HRR,
since we knew DTLS 1.3 was coming in short order, and we want
DTLS 1.3 to be as small a diff from TLS 1.3 as possible.

While you might in theory want to or be able to use TLS 1.3
HRR+cookie to decrease state keeping at the server, that's not (IMO)
the main reason it exists, and so I don't see a need for anyone
to demonstrate that they have done so in order to justify this
portion of the specification.  The text about allowing stateless offload
being a primary purpose for cookie can be true even though it is not
directly utilized in regular TLS.

With respect to the "hash of the ClientHello" question and how much
state is needed, the idea is that the ways in which the second
ClientHello can differ from the original ClientHello are tightly
constrained, such that the original ClientHello can be reconstructed
by the server given the second ClientHello and an honest client.
If the hash of the reconstructed version does not match the hash
saved in the cookie, you assume that some form of attack is underway
and abort the connection.  You can also do fancier things as has
already been described, but that is part of the origin of the "hash of the
ClientHello" text.  (You do also need the hash value to complete the
transcript, as Watson noted.)

With respect to HRR being a weird instance of ServerHello instead of
a "proper" message in its own right, yes, that is weird.  It was
originally a separate message, and then real-world deployment showed
that there were too many deployed middleboxes that would choke on a
new message type, and we had to come up with a *lot* of awkward
hacks to provide "middlebox compatibility mode" (see section D.4).
It seems simpler to make HRR always be the middlebox-compatible version
rather than have two ways to spell it, so that's why it's the way it is.

-Ben

P.S. If you felt like doing some experiments to see how the
stateless HRR affects the memory/CPU balance, it is implemented
in openssl.

---

From: Michael D'Errico <[email-masked]>
Date: Wed, 30 Sep 2020 17:03:05 -0400

> hash of the transcript to ensure that the negotiation isn't interfered

There may be a problem here if you try to implement the
stateless HelloRetryRequest the way the spec. implies (by
sending a hash of ClientHello1 in the "cookie" extension).

A non-conforming client can send an initial ClientHello1,
which both client and server know so they can compute the
hash correctly.  The server puts the hash in the cookie of a
HelloRetryRequest and sends that to the client.  The client
can then put together any ClientHello2 it cares to and
include the cookie from the HelloRetryRequest.

If the server is "stateless" and throws away ClientHello1,
there's no way for it to know that the second ClientHello2
it receives doesn't properly relate to ClientHello1.  The
handshake can still go all the way to completion even
with a bad ClientHello2, I think.  Also the server can't be
actually stateless since it needs to know the HelloRetry-
Request message for the transcript hash, right?

There are a number of changes allowed to be made to the
ClientHello1 that will make it impossible for the server to
recreate the hash sent in the cookie field, even when there
is nothing malicious happening.  Simply changing the
padding extension is one of them.  Pruning the key_share
list is another, as is updating the pre_shared_key list.  So it
can't reject any ClientHello2 which it doesn't hash to the
cookie value.

I don't know what the implications of this are (I've only spent
about 30 minutes reading the spec.) but there appears to be
some room for mischief if a server is "stateless."  Maybe this
should not be allowed out of prudence?  What does this mean
for DTLS 1.3?

Putting a pseudo-session-ticket in the cookie as NSS (?) does
might solve this problem to some extent, but I doubt the
extra processing is worth the tiny amount of memory saved
by tossing the ClientHello1 under normal conditions.  (When
being actively attacked this may be necessary, though I don't
have experience working in a data center so I can't really say.)

However, the RFC should probably not be implying that you
can do stateless HelloRetryRequest by sending a cookie with
just a hash of ClientHello1 (even if the server uses some
integrity protection mechanism on the hash value).

Mike

---

From: Michael D'Errico <[email-masked]>
Date: Wed, 30 Sep 2020 17:24:21 -0400

I wrote:

 > Also the server can't be actually stateless since
 > it needs to know the HelloRetryRequest message
 > for the transcript hash, right?

How can you even implement stateless HRR with a
pseudo-session-ticket in the "cookie"?  The server
needs to know the full HRR message to calculate the
transcript hash, but this can't be part of the ticket
since the ticket is included within the HRR, thus
changing it....

Mike

---

From: Benjamin Kaduk <[email-masked]>
Date: Wed, 30 Sep 2020 14:34:06 -0700

> since the ticket is included within the HRR, thus

The HRR is presumed to be a deterministic function of the
initial ClientHello, and as I discussed in my earlier message,
the server can reconstruct the initial ClientHello from the
second ClientHello and verify it against the hash in the cookie.

-Ben

---

From: Michael D'Errico <[email-masked]>
Date: Wed, 30 Sep 2020 18:53:56 -0400

> second ClientHello and verify it against the hash in the cookie.

I don't believe you can reliably always reconstruct the
initial ClientHello1 from ClientHello2.  Maybe current
TLS 1.3 clients are sending simple enough ClientHello
messages so this is possible today, but what about
next week, next year, etc.?

RFC 8446 lists on pages 27-28 all of the ways the client
is supposed to (or allowed to) change the ClientHello
that gets returned after a HelloRetryRequest:

    -  If a "key_share" extension was supplied in the HelloRetryRequest,
       replacing the list of shares with a list containing a single
       KeyShareEntry from the indicated group.

    -  Removing the "early_data" extension (Section 4.2.10) if one was
       present.  Early data is not permitted after a HelloRetryRequest.

    -  Including a "cookie" extension if one was provided in the
       HelloRetryRequest.

    -  Updating the "pre_shared_key" extension if present by recomputing
       the "obfuscated_ticket_age" and binder values and (optionally)
       removing any PSKs which are incompatible with the server's
       indicated cipher suite.

    -  Optionally adding, removing, or changing the length of the
       "padding" extension [RFC7685].

    -  Other modifications that may be allowed by an extension defined in
       the future and present in the HelloRetryRequest.

The only way stateless HRR could work (I think) is if you sent
the entire ClientHello1 and HelloRetryRequest-minus-cookie
encoded in the cookie somehow, encrypted, integrity-protected.
But a hash of ClientHello1 by itself just won't do.

Mike

---

From: "Michael D'Errico" <[email-masked]>
Date: Wed, 30 Sep 2020 23:34:45 -0400

> Not always; see TCP "fast open" options.

Maybe this should be disabled?  Fortunately if you wanted
to there is a setsockopt for TCP_FASTOPEN.

Mike

---

From: Rob Sayre <[email-masked]>
Date: Wed, 30 Sep 2020 21:33:31 -0700

> to there is a setsockopt for TCP_FASTOPEN.

I am having a difficult time understanding the tradeoffs you're facing.

What software are you working on?

thanks,
Rob