aws / s2n-tls

An implementation of the TLS/SSL protocols
https://aws.github.io/s2n-tls/usage-guide/
Apache License 2.0
4.48k stars 702 forks source link

Derive STEK during handshake from a secret key, certificate and private key. #1078

Open xnuter opened 5 years ago

xnuter commented 5 years ago

Problem:

Currently STEKs are provided to s2n during configuration phase with s2n_config_add_ticket_crypto_key method on per struct s2n_config basis.

However, in context of multiple certificates (e.g., SNI) we'll have to either change the ticket structure, or have a separate s2n_config for each certificate (which might be impractical), or:

Proposed Solution:

Derive a STEK from a secret (which is regularly rotated), and the certificate and the private key which would either are used (during the initial handshake) or would have been used (during session resumption) during handshake time.

For example:

  1. During s2n_config_add_cert_chain_and_key call calculate a fingerprint (e.g. HMAC_SHA256) for the cert/pk pair.
  2. On handshake derive STEK from a secret (we can use same keys configured via s2n_config_add_ticket_crypto_key) and the fingerprint.
  3. Use the STEK for ticket encryption and decryption.

In this case, we have the following benefits:

  1. Session resumption will only work for the same material pair. For example, this is beneficial for customers who use several load-balancers with the corresponding certificates (as sessions can be resumed across them).
  2. s2n users won't have to generate different STEKs for different certificates.
  3. Secrets passed to s2n_config_add_ticket_crypto_key become "rumors" (i.e., could be distributed openly, makes it easier for customers to keep TLS resumption more secure).
  4. The ticket size stays the same (i.e., we don't have to make it larger).

But what about the performance?

s2n_hkdf cost: ~5us per operation so it shouldn't be a problem to derive STEK during a handshake.

The benchmarked code:

        s2n_hmac_new(&hmac);

        s2n_blob_init(&in_key_blob, in_key, 32);
        s2n_blob_init(&salt_blob, salt, 32);
        s2n_blob_init(&info_blob, info, 0);
        s2n_blob_init(&actual_output_blob, output, 32);

        s2n_hkdf(&hmac, S2N_HMAC_SHA256, &salt_blob, 
                        &in_key_blob, &info_blob, &out_result);

        s2n_hmac_free(&hmac);
xonatius commented 4 years ago

s2n_hkdf cost: ~5us per operation so it shouldn't be a problem to derive STEK during a handshake.

Any reason not to derive the keys on s2n_config_add_ticket_crypto_key/s2n_config_add_cert_chain_and_key calls and avoid any additional cost during the handshake? Or cache the derived STEK during handshake?

xnuter commented 4 years ago

s2n_hkdf cost: ~5us per operation so it shouldn't be a problem to derive STEK during a handshake.

Any reason not to derive the keys on s2n_config_add_ticket_crypto_key/s2n_config_add_cert_chain_and_key calls and avoid any additional cost during the handshake? Or cache the derived STEK during handshake?

For SNI use-cases there could be thousands of certs we need to pre-compute and store. We can definitely use lazy compute and cache (if we decide 5 µs per connection is worth creating this machinery).