Subject: [TLS] 0-RTT security considerations (was OPTLS)

From: Nico Williams <[email-masked]>
Date: Tue, 18 Nov 2014 17:46:08 -0600

Following up to the OPTLS proposal I thought it'd be interesting to
explore the security (API, and other) considerations of 0-RTT protocols.
I'm not sure[0] how much this has been done on this list before, so pardon
me if this is noisy.

My experience with 0-RTT is mostly from GSS [RFC2743] and Kerberos
[RFC4120], where the matter was given some explicit treatment treatment
many years ago.  That treatment is not complete, so this should be
relevant to KITTEN WG as well.  I'm cc'ing KITTEN WG, but we should
continue the discussion on the TLS list; Reply-To: is set.

For me the security considerations of 0-RTT have to bleed into APIs in
order to be manageable, which for many TLS apps may well be a deal
killer (and I suspect it generally is).

I.e., I think 0-RTT is generally more trouble than it's worth.

0-RTT means:

   The handshake might be two or three messages, but the client can
   send application data immediately after sending its hello, and
   the server can send application data immediately after consuming
   the client's hello.

This is not a really a new concept[1].

And this concept generalizes to longer exchanges too; the optimization
can be less good than 0-RTT but still better than full latency.

A client can do 0-RTT handshakes whenever it can obtain a usable session
key immediately upon sending the client's first[0] handshake message.

0-RTT could be made available when:

 - doing session resumption
 - the client knows the server's pubkey a priori
 - using PSK

Security considerations:

 - Replay protection (use replay cache or defer protection)

   Replay protection on the server side requires either a replay cache
   (which can more than negate the latency of one network round trip),
   or deferring replay protection availability to the end of the
   handshake.

   Deferring replay protection availability requires that the client's
   first data record(s) be held for delivery until replay protection is
   available (again, limiting the value of 0-RTT), or that the
   application be aware of the replay potential.

 - PFS (not available for 0-RTT data)

   What about PFS?  Can't be done in 0-RTT, but it can become available
   when each party learns the others' ephemeral (EC)DH key.

   Again, the application may (likely will) need to know about PFS being
   deferred, therefore this is an API consideration as well.

 - Server authentication state

   Even in the 0-RTT case the client must check that the server's pubkey
   hasn't been revoked, of course, but either it won't be able to until
   it receives the server's Hello (where stapled OCSP should be found),
   or it will have to check certificate status out of band (which has
   privacy considerations).

   The problem here is that any application data sent before receiving
   the server's Hello will be compromised if the server's private key
   was compromised (even if the cert was revoked).

   For HTTP(S) this is a problem: the HTTP request may or may not be
   sensitive, but the HTTP client implementation and TLS can't know
   if it is -- only the application can know.  This might mean that XHR,
   HTML, need extensions for specifying this.

   Again, this is an API consideration as well.

   DANE makes this consideration go away, mostly[2].

 - Client authentication state

   Imagine a handshake where the client is not authenticated until the
   second round trip, but we have key material for 0-RTT.  The server
   cannot authorize any application protocol commands at this stage.

 - Symmetric session key non-reuse depends entirely on the client and
   its RNG.  E.g., in the resumption and PSK cases.

   When using cipher modes where key/IV reuse is disastrous this could
   be a serious problem.

How to do 0-RTT in non-resumption, non-PSK handshakes:

 - with key transport (the server's static pubkey must be an encryption key)
 - with key agreement (the server's static pubkey must be an (EC)DH key)

PFS can be added, and anyways, it all looks a lot like session
resumption.

How to learn the server's pubkey prior to making the client Hello?

 - use DANE
 - recall the server's pubkey from a previous connection and use it
   optimistically (as in: it hasn't changed since last time)

The latter is the basis of Hugo Krawczyk's OPTLS proposal.

[0] I saw the thread starting at:

    https://www.ietf.org/mail-archive/web/tls/current/msg13298.html

    but the treatment of the security considerations of 0-RTT there was
    not exhaustive, unless I missed it.

[1] The GSS-API [RFC2743] has supported sending application data early,
    and has since 1997 [RFC2078].  GSS calls the "ready to send
    somewhat-protected data" state "prot_ready".  Kerberos V [RFC4120]
    effectively had it even earlier, in 1993 [RFC1510], and probably
    before then too.

[2] Provided one does not object to DANE.

Nico
--

---

From: Eric Rescorla <[email-masked]>
Date: Tue, 18 Nov 2014 16:04:10 -0800

> I'm not sure[0] how much this has been done on this list before, so pardon

A fair bit, including a complete solution in Snap Start
and some handwavy stuff in draft-rescorla-tls13-new-flows-01, as
well as the Watson Ladd mail you reference below

>    application be aware of the replay potential.

Yes, I agree that this doesn't make sense. The server needs to provide
anti-replay as part of the TLS stack using some sort of server-side state.
Servers which don't want to do that should not offer 0-RTT.

>    deferred, therefore this is an API consideration as well.

Yes, we'll need APIs to let the client control whether data should be sent
w/o PFS. Note that the we already have a parallel situation with resumption
which currently never offers OCSP.

>    HTML, need extensions for specifying this.

I'm not following this. Generally, server 0-RTT keys will probably be fairly
short-lived by comparison to OCSP-stapled responses, so you can just
continue to use the key within the OCSP window. Remember that if the
key is compromised within the OCSP window, then the attacker can
attack you with 1-RTT as well as 0-RTT. Again, this is also an issue
with resumption.

>    cannot authorize any application protocol commands at this stage

Every proposal I have ever seen for 0-RTT has the client delivering
client auth in the first flight for exactly this reason.

>    When using cipher modes where key/IV reuse is disastrous this could

The conventional way to address this (as in snap start) is to use an
anti-replay mechanism which ensures uniqueness of the client random,
thus providing key uniqueness.

-Ekr

---

From: Nico Williams <[email-masked]>
Date: Tue, 18 Nov 2014 18:45:45 -0600

On Tue, Nov 18, 2014 at 04:04:10PM -0800, Eric Rescorla wrote:
> >    [...]

But how would the client know the first time?  Perhaps it shouldn't
matter.  The server should just hold back before delivering the data.
Still, in order to do this without a replay cache the handshake has to
have two more messages after the one where the client is prot_ready and
the client has to confirm the early messages.  So this has to be part of
the protocol.

> attack you with 1-RTT as well as 0-RTT. Again, this is also an issue

Yes, this is a general problem that can only really be addressed via key
freshness.

> client auth in the first flight for exactly this reason.

Even ones where the client is afforded confidentiality for its ID?  I
can certainly imagine protocols where that wouldn't be the case.

> thus providing key uniqueness.

By the time the server can check this it's too late: the client sent the
bad ciphertext.

Nico
--

---

From: Eric Rescorla <[email-masked]>
Date: Wed, 19 Nov 2014 11:23:16 -0800

> the client has to confirm the early messages.  So this has to be part of

I'm not following. The idea here is that the server indicates to the
client that it is in principle prepared to do 0-RTT and provides a key
that can be used for that. If the client attempts it and it doesn't work
out (e.g., because the server has lost the key), you fall back to a
1-RTT handshake, so the server can just discard the data rather
than holding it.

If you can send encrypted data to the server, you can also
encrypt the client's certificate. Yes, it's possible to design protocols
where that doesn't work, but it's also possible to design ones where
it does.

> By the time the server can check this it's too late: the client sent the

Good point. I agree that the client needs a strong PRNG.

-Ekr

---

From: Nico Williams <[email-masked]>
Date: Wed, 19 Nov 2014 14:51:19 -0600

On Wed, Nov 19, 2014 at 11:23:16AM -0800, Eric Rescorla wrote:
> > > Yes, I agree that this doesn't make sense. The server needs to
> > > provide anti-replay as part of the TLS stack using some sort of
> > > server-side state.  Servers which don't want to do that should not
> > > offer 0-RTT.
> >
> > But how would the client know the first time?  [...]
> 
> client that it is in principle prepared to do 0-RTT and [...]

Certainly in the resumption case.  However, in other cases, we'd have to
have ensure that whatever oob method is used for establishing the
server's public key also conveys this (e.g., we'd need an RR type for
indicating this for DANE).  It's much easier to have the server hold the
early data and have it bound into the client's next handshake msg.

> can certainly imagine protocols where that wouldn't be the case.

Sure, so can I.  I was describing generic 0-RTT security considerations.
If a specific protocol addresses one of those completely, great.

> where that doesn't work, but it's also possible to design ones where

Yes, of course.  With TLS 1.2 one can renego.  Unless I missed
something, there's nothing in 1.3 for protecting the client's ID.

With DANE one could definitely authenticate the client in a 0-RTT way,
at least if the server has either a public encryption key or a public
key agreement key.

SSHv2, OTOH, is an example of a protocol where key exchange completes
prior to authenticating the user, so in principle one could extend it to
send "early data" and run into this security consideration.  But this is
mostly because SSHv2 is so... shockingly under-optimized as to round
trips...  so perhaps I was reaching with this consideration :)

> Good point. I agree that the client needs a strong PRNG.

Yes, and perhaps it's just not worth pointing out all the ways in which
not having a good RNG is bad.  We take the need for a good RNG as a
given nowadays... (though we should consider ways to minimize dependence
on strong RNGs, see, e.g., EdDSA).

Nico
--

---

From: Eric Rescorla <[email-masked]>
Date: Thu, 20 Nov 2014 09:06:21 -0800

On Wed, Nov 19, 2014 at 12:51 PM, Nico Williams <[email-masked]>
wrote:

> Certainly in the resumption case.

Also in the semi-static DHE cases.

> However, in other cases, we'd have to
> indicating this for DANE).

I don't see that that's a problem. At present DANE doesn't contain enough
information for the client to generate a 0-RTT handshake at all, so as
a practical matter we would need to extend the record format, so that
would implicitly agree to 0-RTT (or explicitly if you prefer).

>   It's much easier to have the server hold the

This is not generically possible, because the client may have used
a key that the server has forgotten, which requires the client to
retransmit.

> something, there's nothing in 1.3 for protecting the client's ID.

In TLS 1.3, the client's second flight is sent encrypted. If it were sent
as part of the first flight, it would also be sent encrypted.

-Ekr

---

From: Nico Williams <[email-masked]>
Date: Fri, 21 Nov 2014 12:51:38 -0600

> Also in the semi-static DHE cases.

Yes, of course (it's like resumption in a way).

> would implicitly agree to 0-RTT (or explicitly if you prefer).

My inclination is to think that adding a new RR type or extending TLSA
for this is not worthwhile.  See below.

> a key that the server has forgotten, which requires the client to

Yes, indeed.  Applications that can retransmit, could do that.  For
other applications (which is to say: most) the result has to be failure,
and then a reconnect.  Not good.  This is a good reason to want to
minimize 0-RTT usage to cases where the client has good reason to think
the server will be able to handle it: when a) the server said or
advertised so earlier, b) not much time has passed since.

0-RTT is an optimization, but if it can lead to failures that
applications must special-case, then that's problematic.  For HTTPS
that's probably not a problem (it's just one reconnect).

Will 1.3 support 0-RTT?

> as part of the first flight, it would also be sent encrypted.

So... is confidentiality protection of the client's cert/ID explicitly
supported in 1.3?  That'd be great news.

Nico
--

---

From: Watson Ladd <[email-masked]>
Date: Fri, 21 Nov 2014 16:55:23 -0800

> advertised so earlier, b) not much time has passed since.

Why wouldn't the implementation of TLS automatically resend 0-RTT data
if the server didn't accept it? This seems like the right solution.

> that's probably not a problem (it's just one reconnect).

Isn't this a charter goal?

> supported in 1.3?  That'd be great news.

Again, I thought this was a charter goal.

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

-- 
"Those who would give up Essential Liberty to purchase a little
Temporary Safety deserve neither  Liberty nor Safety."
-- Benjamin Franklin

---

From: Nico Williams <[email-masked]>
Date: Mon, 24 Nov 2014 00:47:09 -0600

> >> > early data and have it bound into the client's next handshake msg.

Actually, there's no need to bind early data into the handshakes.  It's
enough that the client has to eventually confirm a handshake message
from the server, and for good measure the client should switch to a key
to which the server contributed before sending non-early data.  Then the
server can detect replays.

However, the security consideration remains that replay detection for
early data is not available until the handshake completes.  Thus early
data bearing messages like "launch missiles" must not be acted upon
until the handshake completes.  This is a fairly severe security
consideration...

> if the server didn't accept it? This seems like the right solution.

Agreed.

In the case of the server not having the key with which to decrypt the
early data the only available choices are: a) abort, b) notify the
client app and let it abort or retransmit, c) hold on to the early data
for retransmission.  (a) is not a good idea, and (b) is probably too
complicated (as are all of these security considerations) for many apps,
which leaves (c) (your suggestion) as the best approach to the problem
of the client using a stale key (e.g., a session resumption ticket for
which the server forgot the key) for 0-RTT early data.

Nico
--

---

From: Nico Williams <[email-masked]>
Date: Mon, 24 Nov 2014 04:43:16 -0600

> server can detect replays.

One more note: the server has to know that it got all of the client's
early data...