Subject: [Unbearable] Thoughts on TLS 0-RTT 1.3 compatibility

From: Bill Cox <[email-masked]>
Date: Wed, 23 Mar 2016 06:09:30 -0700

Summary: For HTTP connections, use session caches on both client and
server, and support 0-RTT stateful resumption.  Disallow token binding to
be used to authenticate a stateless 0-RTT connection.  Secure all secret
keys close to the device (including TLS session secrets), and save the
browser's session cache to disk.

As we know, stateless 0-RTT breaks strong client authentication.  All
stateless servers running 0-RTT will fail to finish valid token binding
proofs-of-possession in time to protect first-flight data, leading to
various new and exciting attacks.  IMO, this limitation makes using either
token binding or client certificates with stateless 0-RTT enabled servers a
bad idea.  Even offering support for such a mode reduces security, and
should be avoided.  I have difficulty finding significant real attacks that
are defeated by token binding or client certificates when used over a
stateless 0-RTT connection.  IMO, without a proof of possession, both token
binding and client certificates are nearly pointless.

However, we can safely support one TLS 1.3 0-RTT mode.

IMO, the right way to do 0-RTT token binding over TLS 1.3 is to use session
caches on both the client and server, and to only do 0-RTT during a
resumption.  That way, the proof-of-possession is done on the initial
secure 1-RTT handshake, and the security properties are inherited by future
resumed connections.  The steps in the handshakes are:

During the initial 1-RTT handshake:
- negotiate TB as in TLS 1.2
- server creates a small encrypted ticket containing only the session ID
and a "resumption count" set to 0
- server sends the ticket to the client

During a 0-RTT resumption handshake:
- client sends TB extension, because this might fall back to 1-RTT
- client sends the ticket to the server
- server decrypts the ticket, checks for a cache hit, and drop to 1-RTT if
not found
- server compares the resumption counts in the session state and ticket,
and drops to 1-RTT if they do not match
- server increments the resumption counts in the ticket and session state
- server encryptes the updated ticket and sends it to the client
- server executes 0-RTT HTTP requests from the client's first flight of
packets

Other stateful schemes are possible, such as using strike registers.
However, there is growing evidence that using other stateful server modes
tends to fail in practice.  These schemes are simply too tricky to get
right.  However, session caches have worked for many years and are widely
deployed.

Surprisingly (to me), this even provides full perfect forward secrecy
(PFS).  This is because TLS 1.3 uses a "master resumption secret" to resume
a session, so that even first flight 0-RTT packets are encrypted with new
keys.  The server never writes old session secrets to the cache.  The long
lifetime of the ticket decryption key does not hurt PFS in servers using
session caching with TLS 1.3, unlike stateless servers doing 0-RTT
resumption.

One issue to be resolved is exactly what TLS-unique should be signed during
resumed sessions.  My preference is to remember the original TLS-unique
from the initial session and continue to sign that.  This would allow
servers to also remember which TB headers have already been validated
between connections, greatly reducing the CPU overhead of TB.  A nice way
to enable this to happen would be to specify in TLS 1.3 that the Export Key
Material API should provide the same results in resumed sessions as in the
original 1-RTT connection.  I would prefer this for TLS 1.2 as well, though
I suspect that ship has already sailed.

The security of session-cache based 0-RTT appears to be nearly equivalent
to TLS 1.2 resumption.  The only new security issue I see is that sometimes
the TLS layer will automatically replay 0-RTT application data.  This
happens when the server rejects a 0-RTT handshake and drops to a full 1-RTT
handshake.  In this case, the client is required to resend the 0-RTT
application data.  An attacker can make use of this to cause the
first-flight data to be replayed once.  However, for HTTP, the attacker already
has this capability
<http://blog.valverde.me/2015/12/07/bad-life-advice/#.VvKEt2ErKlG>, and it
applies to all HTTP requests, not just first-flight requests.  Because of
this, I see no reason to restrict first-flight application data from
sending POST requests.  This means that potentially, stateful 0-RTT servers
can be slightly faster than stateless 0-RTT servers.

Making stateful 0-RTT servers really fast means we need high resumption
rates.  I think the #1 reason that QUIC achieves very high 0-RTT rates
compared to either session caches or tickets is that browsers typically do
not write the session cache to disk, while QUIC does write the server
config to disk.  The motivation for not writing the cache to disk is that
this creates a new bearer token, where malware can steal the resumption
data from disk and resume a session elsewhere.  However, as soon as my
laptop hibernates, the session cache is written to disk anyway, and there
is often nothing stopping malware from stealing the cached session from
memory.

The right model, IMO, for protecting secrets is to keep them secured as
close to hardware as possible.  All secret keys should be cryptographically
bound to the device, and unusable on any other device.  This includes the
TLS session secrets.  Using a TPM is too slow, but Skylake Intel processors
have an SGX mode that is clearly fast enough.  Android devices offer
trusted execution environment, which can be fast enough, depending on the
device and software stack.  Alternatively, the OS can employ disk
encryption and modern secure jails for all applications.  Either way, the
result is that secrets are cryptographically bound to the device, even when
written to disk.  On such systems, the browser should just go ahead and
save the cache.

If we do all this, the future for token binding seems promising to me.  If
we instead go down the stateless 0-RTT path, strong client authentication
gets thrown under the bus.

Bill

---

From: Andrei Popov <[email-masked]>
Date: Wed, 23 Mar 2016 17:09:07 +0000

Please correct me if I read this wrong, but the TB-related part of this proposal essentially amounts to removing the requirement that the client prove possession of the TB key on resumption.

This requirement exists today because TLS resumption state is deemed easier to steal than a hardware-bound TB key. Once TLS resumption state is protected in the same way as the TB key, then there will probably be no need for the client to sign with its TB key when resuming a TLS session.

Once TLS 1.3 stabilizes some more, I think we’ll need to write a new document explaining how TB can be used with TLS 1.3.

Cheers,

Andrei

From: Unbearable [mailto:[email-masked]] On Behalf Of Bill Cox
Sent: Wednesday, March 23, 2016 6:10 AM
To: Tokbind WG <[email-masked]>
Subject: [Unbearable] Thoughts on TLS 0-RTT 1.3 compatibility

Summary: For HTTP connections, use session caches on both client and server, and support 0-RTT stateful resumption.  Disallow token binding to be used to authenticate a stateless 0-RTT connection.  Secure all secret keys close to the device (including TLS session secrets), and save the browser's session cache to disk.

As we know, stateless 0-RTT breaks strong client authentication.  All stateless servers running 0-RTT will fail to finish valid token binding proofs-of-possession in time to protect first-flight data, leading to various new and exciting attacks.  IMO, this limitation makes using either token binding or client certificates with stateless 0-RTT enabled servers a bad idea.  Even offering support for such a mode reduces security, and should be avoided.  I have difficulty finding significant real attacks that are defeated by token binding or client certificates when used over a stateless 0-RTT connection.  IMO, without a proof of possession, both token binding and client certificates are nearly pointless.

IMO, the right way to do 0-RTT token binding over TLS 1.3 is to use session caches on both the client and server, and to only do 0-RTT during a resumption.  That way, the proof-of-possession is done on the initial secure 1-RTT handshake, and the security properties are inherited by future resumed connections.  The steps in the handshakes are:

During the initial 1-RTT handshake:
- negotiate TB as in TLS 1.2
- server creates a small encrypted ticket containing only the session ID and a "resumption count" set to 0
- server sends the ticket to the client

During a 0-RTT resumption handshake:
- client sends TB extension, because this might fall back to 1-RTT
- client sends the ticket to the server
- server decrypts the ticket, checks for a cache hit, and drop to 1-RTT if not found
- server compares the resumption counts in the session state and ticket, and drops to 1-RTT if they do not match
- server increments the resumption counts in the ticket and session state
- server encryptes the updated ticket and sends it to the client
- server executes 0-RTT HTTP requests from the client's first flight of packets

Other stateful schemes are possible, such as using strike registers.  However, there is growing evidence that using other stateful server modes tends to fail in practice.  These schemes are simply too tricky to get right.  However, session caches have worked for many years and are widely deployed.

Surprisingly (to me), this even provides full perfect forward secrecy (PFS).  This is because TLS 1.3 uses a "master resumption secret" to resume a session, so that even first flight 0-RTT packets are encrypted with new keys.  The server never writes old session secrets to the cache.  The long lifetime of the ticket decryption key does not hurt PFS in servers using session caching with TLS 1.3, unlike stateless servers doing 0-RTT resumption.

One issue to be resolved is exactly what TLS-unique should be signed during resumed sessions.  My preference is to remember the original TLS-unique from the initial session and continue to sign that.  This would allow servers to also remember which TB headers have already been validated between connections, greatly reducing the CPU overhead of TB.  A nice way to enable this to happen would be to specify in TLS 1.3 that the Export Key Material API should provide the same results in resumed sessions as in the original 1-RTT connection.  I would prefer this for TLS 1.2 as well, though I suspect that ship has already sailed.

The security of session-cache based 0-RTT appears to be nearly equivalent to TLS 1.2 resumption.  The only new security issue I see is that sometimes the TLS layer will automatically replay 0-RTT application data.  This happens when the server rejects a 0-RTT handshake and drops to a full 1-RTT handshake.  In this case, the client is required to resend the 0-RTT application data.  An attacker can make use of this to cause the first-flight data to be replayed once.  However, for HTTP, the attacker already has this capability<https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fblog.valverde.me%2f2015%2f12%2f07%2fbad-life-advice%2f%23.VvKEt2ErKlG&data=01%7c01%7cAndrei.Popov%40microsoft.com%7cd3967ab02d0c42aa5ae908d3531e40ed%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=9a8wCtUBnGY7XDpk75SHmZoXGcol7pIgN7YUC5oJERA%3d>, and it applies to all HTTP requests, not just first-flight requests.  Because of this, I see no reason to restrict first-flight application data from sending POST requests.  This means that potentially, stateful 0-RTT servers can be slightly faster than stateless 0-RTT servers.

Making stateful 0-RTT servers really fast means we need high resumption rates.  I think the #1 reason that QUIC achieves very high 0-RTT rates compared to either session caches or tickets is that browsers typically do not write the session cache to disk, while QUIC does write the server config to disk.  The motivation for not writing the cache to disk is that this creates a new bearer token, where malware can steal the resumption data from disk and resume a session elsewhere.  However, as soon as my laptop hibernates, the session cache is written to disk anyway, and there is often nothing stopping malware from stealing the cached session from memory.

The right model, IMO, for protecting secrets is to keep them secured as close to hardware as possible.  All secret keys should be cryptographically bound to the device, and unusable on any other device.  This includes the TLS session secrets.  Using a TPM is too slow, but Skylake Intel processors have an SGX mode that is clearly fast enough.  Android devices offer trusted execution environment, which can be fast enough, depending on the device and software stack.  Alternatively, the OS can employ disk encryption and modern secure jails for all applications.  Either way, the result is that secrets are cryptographically bound to the device, even when written to disk.  On such systems, the browser should just go ahead and save the cache.

If we do all this, the future for token binding seems promising to me.  If we instead go down the stateless 0-RTT path, strong client authentication gets thrown under the bus.

Bill

---

From: Bill Cox <[email-masked]>
Date: Wed, 23 Mar 2016 11:43:57 -0700

On Wed, Mar 23, 2016 at 10:09 AM, Andrei Popov <[email-masked]>
wrote:

> Please correct me if I read this wrong, but the TB-related part of this
> proposal essentially amounts to removing the requirement that the client
> prove possession of the TB key on resumption.
>

Correct.  There is no opportunity to prove possession again on a 0-RTT
resumption.  In any case, protecting all secrets rather than just the
private keys will better protect the client.

>
>
> This requirement exists today because TLS resumption state is deemed
> easier to steal than a hardware-bound TB key. Once TLS resumption state is
> protected in the same way as the TB key, then there will probably be no
> need for the client to sign with its TB key when resuming a TLS session.
>

Yep.  This was done for token binding because the session state should be
easier to steal.  However, it is not done for client certificates, and an
attacker with the saved session  state does not need access to the cert to
resume the connection.

Instead of encrypting the session cache, I would prefer to have just the
session secrets protected.  That would let us use a cross-platform generic
crypto API that could be used with any TLS implementation.

I would prefer that we start thinking in terms of protecting all secrets
rather than just a few private keys.  If we secure the secrets, we can have
secure 0-RTT resumption.

Bill

---

From: Andrei Popov <[email-masked]>
Date: Wed, 23 Mar 2016 19:37:19 +0000

Ø  I would prefer that we start thinking in terms of protecting all secrets rather than just a few private keys.  If we secure the secrets, we can have secure 0-RTT resumption.

Yes, I agree with this. For TLS 1.3, this could be our way to enable TB with 0-RTT, at least where the hardware allows secure storage of TLS secrets (and not just TB private keys).

From: Bill Cox [mailto:[email-masked]]
Sent: Wednesday, March 23, 2016 11:44 AM
To: Andrei Popov <[email-masked]>
Cc: Tokbind WG <[email-masked]>
Subject: Re: [Unbearable] Thoughts on TLS 0-RTT 1.3 compatibility

On Wed, Mar 23, 2016 at 10:09 AM, Andrei Popov <[email-masked]<mailto:[email-masked]>> wrote:
Please correct me if I read this wrong, but the TB-related part of this proposal essentially amounts to removing the requirement that the client prove possession of the TB key on resumption.

Correct.  There is no opportunity to prove possession again on a 0-RTT resumption.  In any case, protecting all secrets rather than just the private keys will better protect the client.

Yep.  This was done for token binding because the session state should be easier to steal.  However, it is not done for client certificates, and an attacker with the saved session  state does not need access to the cert to resume the connection.

Instead of encrypting the session cache, I would prefer to have just the session secrets protected.  That would let us use a cross-platform generic crypto API that could be used with any TLS implementation.

I would prefer that we start thinking in terms of protecting all secrets rather than just a few private keys.  If we secure the secrets, we can have secure 0-RTT resumption.

Bill

---

From: Martin Thomson <[email-masked]>
Date: Thu, 24 Mar 2016 17:06:50 +1100

On 24 March 2016 at 06:37, Andrei Popov <[email-masked]> wrote:
> Ø  I would prefer that we start thinking in terms of protecting all secrets
> Yes, I agree with this. For TLS 1.3, this could be our way to enable TB with
> 0-RTT, at least where the hardware allows secure storage of TLS secrets (and
> not just TB private keys).

I think that I disagree.  A token binding key has an opportunity to be
much better protected than whatever is used for resumption (which,
accordingly, has a much shorter lifetime).

I don't have an answer for the 0-RTT aspects of this.  I suspect that
the right answer is to not send any token binding proofs until the
handshake is complete, but I can appreciate how that might make people
sad.

---

From: Bill Cox <[email-masked]>
Date: Thu, 24 Mar 2016 08:34:21 -0700

> accordingly, has a much shorter lifetime).

I think I might be able to convince you :)

In TLS 1.3, the master resumption secret in a secure 0-RTT mode gets used
exactly once per resumption, the same as TB keys in TLS 1.2.  If we protect
the resumption secret exactly like we protect the TB private key, then TLS
1.3 0-RTT will have essentially the same TB latency as TLS 1.2.  If we use
the 0-RTT mode I described above, It should also have the same security.

0-RTT is coming on like a freight train.  I suspect the world will mostly
run on 0-RTT in about 3 years.  This is the only way I see for TB to be
effective for everyone in that future.

> handshake is complete, but I can appreciate how that might make people

I also think we should not send any application requests before the TB
proof.  That means we must choose between two options:

1) Don't allow 0-RTT in any form.
2) Secure the master resumption secrets as well as TB private keys, and
don't do TB proofs on 0-RTT resumption.

If there more positive stories about companies choosing security over
short-term profits, I would prefer option 1.

Bill

---

From: Andrei Popov <[email-masked]>
Date: Thu, 24 Mar 2016 17:47:34 +0000

Ø  I suspect that the right answer is to not send any token binding proofs until the handshake is complete, but I can appreciate how that might make people sad.
This was my thinking originally, but if resumption secrets are equally well-protected as the TB key, then why prove possession of the TB key at resumption time?

One caveat is that for TB keys we could potentially attest to the server that the key us hardware-bound, however similar attestation for resumption secrets seems unlikely to happen. But then those high-security servers that will insist on attested hardware-bound TB keys can probably disable resumption and accept increased latency.

From: Bill Cox [mailto:[email-masked]]
Sent: Thursday, March 24, 2016 8:34 AM
To: Martin Thomson <[email-masked]>
Cc: Andrei Popov <[email-masked]>; Tokbind WG <[email-masked]>
Subject: Re: [Unbearable] Thoughts on TLS 0-RTT 1.3 compatibility

On Wed, Mar 23, 2016 at 11:06 PM, Martin Thomson <[email-masked]<mailto:[email-masked]>> wrote:

In TLS 1.3, the master resumption secret in a secure 0-RTT mode gets used exactly once per resumption, the same as TB keys in TLS 1.2.  If we protect the resumption secret exactly like we protect the TB private key, then TLS 1.3 0-RTT will have essentially the same TB latency as TLS 1.2.  If we use the 0-RTT mode I described above, It should also have the same security.

0-RTT is coming on like a freight train.  I suspect the world will mostly run on 0-RTT in about 3 years.  This is the only way I see for TB to be effective for everyone in that future.

I also think we should not send any application requests before the TB proof.  That means we must choose between two options:

1) Don't allow 0-RTT in any form.
2) Secure the master resumption secrets as well as TB private keys, and don't do TB proofs on 0-RTT resumption.

If there more positive stories about companies choosing security over short-term profits, I would prefer option 1.

Bill

---

From: Martin Thomson <[email-masked]>
Date: Fri, 25 Mar 2016 15:42:06 +1100

On 25 March 2016 at 04:47, Andrei Popov <[email-masked]> wrote:
> This was my thinking originally, but if resumption secrets are equally
> well-protected as the TB key, then why prove possession of the TB key at
> resumption time?

I don't get this line of reasoning at all.  Resumption secrets don't
get this enhanced level of protection without effort, and I'm not
seeing any incentive to protect something like this to that degree.
It's short-lived, and easily regenerated.  A TB key is, at least to
some degree, valuable over a moderately long period.

A TB key[46] can benefit from existing infrastructure for storing
asymmetric keys for authentication.  Resumption secrets need
TLS-version-specific logic in their use, which makes integration into
HSM-like implementations much less appealing.

--Martin

[46] I really hope we aren't talking about the product of the
exporter, because that's something that you generate and discard
immediately.

---

From: Andrei Popov <[email-masked]>
Date: Fri, 25 Mar 2016 17:10:33 +0000

> A TB key[46] can benefit from existing infrastructure for storing asymmetric keys for authentication.  
> Resumption secrets need TLS-version-specific logic in their use, which makes integration into HSM-like implementations much less appealing.

Correct, extending strong protection to TLS resumption secrets is a significant amount of work for a TLS implementer. I also think that the appropriate hardware will not be universally available. However, in those cases where the TLS resumption secrets are strongly protected, with appropriate HW support present, it may be possible to avoid proving possession of the TB key on TLS resumption. And it may be the only way to use TB in TLS1.3 0-RTT mode, while preserving security and without adding round-trips.

> Resumption secrets don't get this enhanced level of protection without effort, and I'm not seeing any incentive to protect something like this to that degree.

Totally agree about the effort, but how about these incentives:
1. Prevent attackers from exporting TLS session resumption secrets;
2. Enable more 0-RTT resumption in TLS (secure resumption secrets might be longer-lived);
3. Enable TB in 0-RTT mode.

Cheers,

Andrei

-----Original Message-----
From: Martin Thomson [mailto:[email-masked]] 
Sent: Thursday, March 24, 2016 9:42 PM
To: Andrei Popov <[email-masked]>
Cc: Bill Cox <[email-masked]>; Tokbind WG <[email-masked]>
Subject: Re: [Unbearable] Thoughts on TLS 0-RTT 1.3 compatibility

On 25 March 2016 at 04:47, Andrei Popov <[email-masked]> wrote:
> well-protected as the TB key, then why prove possession of the TB key 
> at resumption time?

I don't get this line of reasoning at all.  Resumption secrets don't get this enhanced level of protection without effort, and I'm not seeing any incentive to protect something like this to that degree.
It's short-lived, and easily regenerated.  A TB key is, at least to some degree, valuable over a moderately long period.

A TB key[46] can benefit from existing infrastructure for storing asymmetric keys for authentication.  Resumption secrets need TLS-version-specific logic in their use, which makes integration into HSM-like implementations much less appealing.

--Martin

[46] I really hope we aren't talking about the product of the exporter, because that's something that you generate and discard immediately.

---

From: Martin Thomson <[email-masked]>
Date: Tue, 29 Mar 2016 10:15:02 +1100

> 1. Prevent attackers from exporting TLS session resumption secrets;

Cost-benefit.  If I could be convinced that it was worth the cost,
then maybe.  Even a handful of milliseconds is probably too much
though.

> 2. Enable more 0-RTT resumption in TLS (secure resumption secrets might be longer-lived);

0-RTT is pretty common already.  And protection on the secrets isn't
the only thing to consider when extending the lifetime of a secret.
(The server doesn't know what protections are in place, so it's going
to have its own limits, then there's all the other factors...)

> 3. Enable TB in 0-RTT mode.

That's not an incentive.  To me, in any case.  TB isn't an ends, it's a means.