tlswg / tls13-spec

TLS 1.3 Specification
563 stars 159 forks source link

Early Data after HelloRetryRequest #972

Closed hannestschofenig closed 7 years ago

hannestschofenig commented 7 years ago

Section 4.1.2 says that "Early data is not permitted after HelloRetryRequest."

In TLS the use of the HRR is a rare occurrence since it is really only used when the server finds an acceptable set of parameters but the ClientHello does not contain sufficient information to proceed with the handshake. For example, the client does not provide a key_share appropriate for the use by the server.

In DTLS, however, the use of a HelloRetryRequest will be more common since it replaces the return routability check. Hence, when a HRR is sent the resulting exchange leads to two round trips before the client can send application data. With the use of early data following the HRR message the client cut down the exchange to one round trip.

The TLS specification does not give a justification why this constraint has been added.

It is possible to relax this requirement in the DTLS 1.3 specification where the scenario is problemantic or to also address it in the TLS 1.3 spec.

PS: Thanks to Mark Dunn in his review https://www.ietf.org/mail-archive/web/tls/current/msg22947.html for making this observation.

martinthomson commented 7 years ago

It is possible to relax the requirement in DTLS 1.3 (in which case, this issue moves over there). However, I think that it might be an optimization and complication we can avoid.

In practice, implementing two bites at 0-RTT is difficult, especially for DTLS. If both initial ClientHello and second ClientHello are followed by early data, then you have two lots of early data with different keys and the same epoch. That's sort-of OK because the datagrams you don't want get discarded when they don't decrypt, but it is messy. There is also a bunch of logic that is simplified by only having one attempt at sending early data.

The technique that QUIC uses here is to bind source address validation into the session ticket. If you do that, and conditions haven't changed very much, you can avoid sending an HRR for address validation sometimes. And if the primary reason for doing address validation is amplification attack, early data actually reduces the problem by giving the server lots more inbound data: more inbound data allows the server to send more data in response without worrying about an increased amplification factor.

The other reason you send HRR is to avoid commitment of processing resources based on unvalidated traffic. In that case, you shouldn't accept 0-RTT.

hannestschofenig commented 7 years ago

I was actually thinking about doing a normal ClientHello, which will result in the HRR exchange. Then, the client uses a 0-RTT exchange. So, there wouldn't be two early data payloads send around. I agree that would be ugly.

But you raise an interesting point: The HRR was really designed for TLS and does not necessarily focus on the return-routability check concept (which can even be seen from the description in Section 4.1.4).

Since the HRR message will be quite common for connectionless transports and the client and server are most likely aware of groups the two peers support I am wondering whether we could design the following exchange in DTLS 1.3 to avoid sending key shares and other information twice. The return-routability extension is an extension that hints to the server that the initial ClientHello is really only used for return-routability checking.

     Client                                               Server

     ClientHello
     + return-routability             -------->
                                      <--------         HelloRetryRequest
                                                        + cookie

Then, with the second ClientHello the client provides all the necessary information to proceed with the exchange.

     ClientHello
     + supported_groups
     + signature_algorithms
     + cookie
     + key_share             -------->

How does that sound?

martinthomson commented 7 years ago

I've proposed using cookie for return routeability. No need for anything more complicated.

hannestschofenig commented 7 years ago

The cookie for return-routability is fine. The problem is only that you are essentially in DTLS sending data twice, once with the initial ClientHello and then again with the retransmitted ClientHello that is sent in response to the HRR from the server.

Do you see my problem?

martinthomson commented 7 years ago

The cost of constructing a ClientHello in that case isn't that high, and the size of the message isn't too bad either. The biggest costs you can avoid by not including key shares. The handshake requires that you provide PSK binders, but the cost of calculating and sending that isn't so high.

hannestschofenig commented 7 years ago

There are two issues:

First, a device that starts with a public key based authentication in DTLS will have to send the parameters twice. Useless data transmission for no good purpose.

Second, TLS 1.3 currently does not allow a client to allow a 0-RTT exchange following an HRR.

For devices that use DTLS 1.3 that's not a good situation considering that some of the radio technologies have very small MTU sizes, see https://tools.ietf.org/html/draft-ietf-lpwan-overview-01

ekr commented 7 years ago

I'm not following the concern here: you can only provide 0-RTT when you have a PSK, in which case the PSK label should contain whatever authenticator you need for the return routability check. Obviously, you could be mobile and want to retroactively bless the data you sent in 0-RTT but that seems like an edge case. I'd rather fix this by revising the DTLS advice to say that you probably don't need the cookie exchange if you are doing PSK and stuff an address token in the label. Note that this will also improve DTLS performance.