In TLS, at a high level there are two phases: a handshake phase where asymmetric cryptography is used by two ends (server and client) to agree on a shared key, and a second phase for data transmission where that shared key is used to encrypt/decrypt data. The first phase is generally more expensive than the second; it's computationally intense to agree on a key, and it takes several network round trips to do.
To save time, and cpu, TLS has two mechanisms for resuming connections using the same shared key that was previously agreed upon. One is session caching where the server and client each independently cache a session and optionally use it to resume. A problem with this though is that when the server side is a distributed application across many instances or servers then some kind of distributed shared cache is needed. So the mechanism is TLS session tickets. With tickets, the server side wraps its copy of the session data in some robust encryption and then asks the client to store it, just like a browser stores cookies. To resume, the client provides the server with the ticket - it decrypts it, and now it knows everything it needs to resume. So as long as the servers for a site all have the same key, everything works fine.
The hard thing about session tickets is managing the keys encrypting the tickets themselves. These keys have to be shared by all of the servers for a site, and since the keys can be used to decrypt all of the details of every session handled by the servers, they have the potential to undo the security of TLS itself.
Sadly, most session ticket key implementations are terrible and people hardcode a single key used by many servers, and they never rotate it. With s2n, we want to do much better: to construct an API that makes it very hard to get ticket key rotation wrong and overwhelmingly guides an implementor (and hence operatotrs) through the right thing.
s2n_config_add_ticket_encryption_key(const void *id, int id_len,
const void *key, int key_len,
uint64_t expiration_time_in_nanos_since_epoch);
Behind the scenes, s2n would:
- Take the given key and use HKDF2 (we need to implement this anyway for TLS1.3) to expand whatever the caller gave us into a more robust key.
- Order all of the keys its been given by expiration time.
- Issue tickets using the key that is closest to its expiration time, as long as that expiration time is within the next 6 hours.
- Stop using a key if it is 5 hours or nearer until its expiration time.
- Erase any keys that have gone beyond their expiration time.
- Limit to 48 (or something reasonable) the total number of keys.
Therefore keys would be used for an hour each, but up to two days worth may be pre-loaded, and the sessions they encrypt would be valid for between 5 and 6 hours.
WDYT?