More Privacy, Less Latency
Improved Handshakes in TLS version 1.3
Please note that this post is about draft-11 of the TLS v1.3 standard.
TLS must be fast. Adoption will greatly benefit from speeding up the initial handshake that authenticates and secures the connection. You want to get the protocol out of the way and start delivering data to visitors as soon as possible. This is crucial if we want the web to succeed at deprecating non-secure HTTP.
Let’s start by looking at full handshakes as standardized in TLS v1.2, and then continue to abbreviated handshakes that decrease connection times for resumed sessions. Once we understand the current protocol we can proceed to proposals made in the latest TLS v1.3 draft to achieve full 1-RTT and even 0-RTT handshakes.
It helps if you already have a rough idea of how TLS and Diffie-Hellman work as I can’t go into every detail. The focus of this post is on comparing current and future handshakes and I might omit a few technicalities to get basic ideas across more easily.
Full TLS 1.2 Handshake (static RSA)
Static RSA is a straightforward key exchange method, available since
SSLv2. After
sharing basic protocol information via the ClientHello
and ServerHello
messages the server sends its certificate to the client. ServerHelloDone
signals that for now there will be no further messages until the client
responds.
The client then encrypts the so-called premaster secret with the server’s
public key found in the certificate and wraps it in a ClientKeyExchange
message. ChangeCipherSpec
signals that from now on messages will be encrypted.
Finished
, the first message to be encrypted and the client’s last message of
the handshake, contains a MAC of all handshake messages exchanged thus far to
prove that both parties saw the same messages, without interference from a MITM.
The server decrypts the premaster secret found in the ClientKeyExchange
message using its certificate’s private key, and derives the master secret and
communication keys. It then too signals a switch to encrypted communication
and completes the handshake. It takes two round-trips to establish a
connection.
Authentication: With static RSA key exchanges, the connection is
authenticated by encrypting the premaster secret with the server certificate’s
public key. Only the server in possession of the private key can decrypt,
correctly derive the master secret, and send an encrypted Finished
message
with the right MAC.
The simplicity of static RSA has a serious drawback: it does not offer forward secrecy. If a passive adversary records all traffic to a server then every recorded TLS session can be broken later by obtaining the certificate’s private key.
This key exchange method will be removed in TLS v1.3.
Full TLS 1.2 Handshake (ephemeral DH)
A full handshake using (Elliptic Curve)
Diffie-Hellman to
exchange ephemeral keys is very similar to the flow of static RSA. The main
difference is that after sending the certificate the server will also send a
ServerKeyExchange
message. This message contains either the parameters of a
DH group or of an elliptic curve, paired with an ephemeral public key computed
by the server.
The client too computes an ephemeral public key compatible with the given parameters and sends it to the server. Knowing their private keys and the other party’s public key both sides should now share the same premaster secret and can derive a shared master secret.
Authentication: With (EC)DH key exchanges it’s still the certificate that
must be signed by a CA listed in the client’s trust store. To authenticate the
connection the server will sign the parameters contained in ServerKeyExchange
with the certificate’s private key. The client verifies the signature with the
certificate’s public key and only then proceeds with the handshake.
Abbreviated Handshakes in TLS 1.2
Since SSLv2 clients have been able to use session identifiers as a way to resume previously established TLS/SSL sessions. Session resumption is important because a full handshake can take time: it has a high latency as it needs two round-trips and might involve expensive computation to exchange keys, or sign and verify certificates.
Session IDs, assigned
by the server, are unique identifiers under which both parties store the master
secret and other details of the connection they established. The client may
include this ID in the ClientHello
message of the next handshake to
short-circuit the negotiation and reuse previous connection parameters.
If the server is willing and able to resume the session it responds with a
ServerHello
message including the Session ID given by the client. This
handshake is effectively 1-RTT as the client can send application data
immediately after the Finished
message.
Sites with lots of visitors will have to manage and secure big session caches, or risk pushing out saved sessions too quickly. A setup involving multiple load-balanced servers will need to securely synchronize session caches across machines. The forward secrecy of a connection is bounded by how long session information is retained on servers.
Session tickets, created by the server
and stored by the client, are blobs containing all necessary information about
a connection, encrypted by a key only known to the server. If the client
presents this tickets with the ClientHello
message, and proves that it knows
the master secret stored in the ticket, the session will be resumed.
A server willing and able to decrypt the given ticket responds with a
ServerHello
message including an empty SessionTicket extension, otherwise
the extension would be omitted completely. As with session IDs, the client will
start sending application data immediately after the Finished
message to
achieve 1-RTT.
To not affect the forward secrecy provided by (EC)DHE suites session ticket keys should be rotated periodically, otherwise stealing the ticket key would allow recovering recorded sessions later. In a setup with multiple load-balanced servers the main challenge here is to securely generate, rotate, and synchronize keys across machines.
Authentication: Both session resumption mechanisms retain the client’s and server’s authentication states as established in the session’s initial handshake. Neither the server nor the client have to send and verify certificates a second time, and thus can reduce connection times significantly, especially when dealing with RSA certificates.
Full Handshakes in TLS 1.3
The first good news about handshakes in TLS v1.3 is that static RSA key exchanges are no longer supported. Great! That means we can start with full handshakes using forward-secure Diffie-Hellman.
Another important change is the removal of the ChangeCipherSpec
protocol
(yes, it’s actually a protocol, not a message). With TLS v1.3 every message
sent after ServerHello
is encrypted with the so-called
ephemeral secret to lock
out passive adversaries very early in the game. EncryptedExtensions
carries
Hello extension data that must be encrypted because it’s not needed to set up
secure communication.
The probably most important change with regard to 1-RTT is the removal of the
ServerKeyExchange
and ClientKeyExchange
messages. The DH parameters and
public keys are now sent in special KeyShare extensions, a new type of
extension to be included in the ServerHello
and ClientHello
messages.
Moving this data into Hello extensions keeps the handshake compatible with TLS
v1.2 as it doesn’t change the order of messages.
The client sends a list of KeyShareEntry values, each consisting of a named
(EC)DH group and an ephemeral public key. If the server accepts it must respond
with one of the proposed groups and its own public key. If the server does not
support any of the given key shares the server will request retrying the
handshake or abort the connection with a fatal handshake_failure
alert.
Authentication: The Diffie-Hellman parameters itself aren’t signed anymore,
authentication will be a tad more explicit in TLS v1.3. The server sends a
CertificateVerify
message that contains a hash of all handshake message
exchanged so far, signed with the certificate’s private key. The client then
simply verifies the signature with the certificate’s public key.
Session Resumption in TLS 1.3 (PSK)
Session resumption via identifiers and tickets is obsolete in TLS v1.3. Both methods are replaced by a pre-shared key (PSK) mode. A PSK is established on a previous connection after the handshake is completed, and can then be presented by the client on the next visit.
The client sends one or more PSK identities as opaque blobs of data. They can be database lookup keys (similar to Session IDs), or self-encrypted and self-authenticated values (similar to Session Tickets). If the server accepts one of the given PSK identities it replies with the one it selected. The KeyShare extension is sent to allow servers to ignore PSKs and fall back to a full handshake.
Forward secrecy can be maintained by limiting the lifetime of PSK identities sensibly. Clients and servers may also choose an (EC)DHE cipher suite for PSK handshakes to provide forward secrecy for every connection, not just the whole session.
Authentication: As in TLS v1.2, the client’s and server’s authentication states are retained and both parties don’t need to exchange and verify certificates again. A regular PSK handshake initiating a new session, instead of resuming, omits certificates completely.
Session resumption still allows significantly faster handshakes when using RSA certificates and can prevent user-facing client authentication dialogs on subsequent connections. However, the fact that it requires a single round-trip just like a full handshake might make it less appealing, especially if you have an ECDSA or EdDSA certificate and do not require client authentication.
Zero-RTT Handshakes in TLS 1.3
The latest draft of the specification contains a proposal to let clients
encrypt application data and include it in their first flights. On a previous
connection, after the handshake completes, the server would send a
ServerConfiguration
message that the client can use for
0-RTT handshakes
on subsequent connections. The
configuration
includes a configuration identifier, the server’s semi-static (EC)DH parameters,
an expiration date, and other details.
With the very first TLS record the client sends its ClientHello
and, changing
the order of messages, directly appends application data (e.g. GET / HTTP/1.1
).
Everything after the ClientHello
will be encrypted with the
static secret, derived from
the client’s ephemeral KeyShareEntry and the semi-static DH parameters given
in the server’s configuration. The end_of_early_data
alert indicates the end
of the flight.
The server, if able and willing to decrypt, responds with its default set of
messages and immediately appends the contents of the requested resource. That’s
the same round-trip time as for an unencrypted HTTP request. All communication
following the ServerHello
will again be encrypted with the ephemeral secret,
derived from the client’s and server’s ephemeral key shares. After exchanging
Finished
messages the server will be re-authenticated, and traffic encrypted
with keys derived from the master secret.
Security of 0-RTT Handshakes
At first glance, 0-RTT mode seems similar to session resumption or PSK, and you might wonder why one wouldn’t merge these mechanisms. The differences however are subtle but important, and the security properties of 0-RTT handshakes are weaker than those for other kinds of TLS data:
1. To protect against replay attacks the server must incorporate a server
random into the master secret. That is unfortunately not possible before the
first round-trip and so the poor server can’t easily tell whether it’s a valid
request or an attacker replaying a recorded conversation. Replay protection
will be in place again after the ServerHello
message is sent.
2. The semi-static DH share given in the server configuration, used to derive the static secret and encrypt first flight data, defies forward secrecy. We need at least one round-trip to establish the ephemeral secret. As configurations are shared between clients, and recovering the server’s DH share becomes more attractive, expiration dates should be limited sensibly. The maximum allowed validity is 7 days.
3. If the server’s DH share is compromised a MITM can tamper with the 0-RTT data sent by the client, without being detected. This does not extend to the full session as the client can retrospectively authenticate the server via the remaining handshake messages.
Defending against Replay Attacks
Thwarting replay attacks without input from the server is fundamentally very expensive. It’s important to understand that this is a generic problem, not an issue with TLS in particular, so alas one can’t just borrow another protocol’s 0-RTT model and put that into TLS.
It is possible to have servers keep a list of every ClientRandom they have
received in a given time window. Upon receiving a ClientHello
the server
checks its list and rejects replays if necessary. This list must be globally
and temporally consistent as there are
possible attack vectors
due to TLS’ reliable delivery guarantee if an attacker can force a server to
lose its state, as well as with multiple servers in loosely-synchronized data
centers.
Maintaining a consistent global state is possible, but only in some limited circumstances, namely for very sophisticated operators or situations where there is a single server with good state management. We will need something better.
Removing Anti-Replay Guarantee
A possible solution might be a TLS stack API to let applications designate
certain data as replay-safe, for example GET / HTTP/1.1
assuming that GET
requests against a given resource are idempotent.
Applications can, before opening the connection, specify replayable 0-RTT data to send on the first flight. If the server ignores the given 0-RTT data, the TLS stack automatically replays it after the first round-trip.
Removing Reliable Delivery Guarantee
Another way of achieving the same outcome would be a TLS stack API that again lets applications designate certain data as replay-safe, but does not automatically replay if the server ignores it. The application can decide to do this manually if necessary.
Both of these APIs are early proposals and the final version of the specification might look very different from what we can see above. Though, as 0-RTT handshakes are a charter goal, the working group will very likely find a way to make them work.
Summing up
TLS v1.3 will bring major improvements to handshakes, how exactly will be finalized in the coming months. They will be more private by default as all information not needed to set up a secure channel will be encrypted as early as possible. Clients will need only a single round-trip to establish secure and authenticated connections to servers they never spoke to before.
Static RSA mode will no longer be available, forward secrecy will be the default. The two session resumption standards, session identifiers and session tickets, are merged into a single PSK mode which will allow streamlining implementations.
The proposed 0-RTT mode is promising, for custom application communication
based on TLS but also for browsers, where a GET / HTTP/1.1
request to your
favorite news page could deliver content blazingly fast as if no TLS was
involved. The security aspects of zero round-trip handshakes will become more
clear as the draft progresses.