summaryrefslogtreecommitdiff
path: root/src/ssl/ssl_session.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/ssl/ssl_session.cc')
-rw-r--r--src/ssl/ssl_session.cc89
1 files changed, 69 insertions, 20 deletions
diff --git a/src/ssl/ssl_session.cc b/src/ssl/ssl_session.cc
index a1c21dc8..6bacc806 100644
--- a/src/ssl/ssl_session.cc
+++ b/src/ssl/ssl_session.cc
@@ -227,24 +227,15 @@ UniquePtr<SSL_SESSION> SSL_SESSION_dup(SSL_SESSION *session, int dup_flags) {
new_session->verify_result = session->verify_result;
- new_session->ocsp_response_length = session->ocsp_response_length;
if (session->ocsp_response != NULL) {
- new_session->ocsp_response = (uint8_t *)BUF_memdup(
- session->ocsp_response, session->ocsp_response_length);
- if (new_session->ocsp_response == NULL) {
- return nullptr;
- }
+ new_session->ocsp_response = session->ocsp_response;
+ CRYPTO_BUFFER_up_ref(new_session->ocsp_response);
}
- new_session->tlsext_signed_cert_timestamp_list_length =
- session->tlsext_signed_cert_timestamp_list_length;
- if (session->tlsext_signed_cert_timestamp_list != NULL) {
- new_session->tlsext_signed_cert_timestamp_list = (uint8_t *)BUF_memdup(
- session->tlsext_signed_cert_timestamp_list,
- session->tlsext_signed_cert_timestamp_list_length);
- if (new_session->tlsext_signed_cert_timestamp_list == NULL) {
- return nullptr;
- }
+ if (session->signed_cert_timestamp_list != NULL) {
+ new_session->signed_cert_timestamp_list =
+ session->signed_cert_timestamp_list;
+ CRYPTO_BUFFER_up_ref(new_session->signed_cert_timestamp_list);
}
OPENSSL_memcpy(new_session->peer_sha256, session->peer_sha256,
@@ -437,6 +428,59 @@ int ssl_get_new_session(SSL_HANDSHAKE *hs, int is_server) {
return 1;
}
+int ssl_ctx_rotate_ticket_encryption_key(SSL_CTX *ctx) {
+ OPENSSL_timeval now;
+ ssl_ctx_get_current_time(ctx, &now);
+ {
+ /* Avoid acquiring a write lock in the common case (i.e. a non-default key
+ * is used or the default keys have not expired yet). */
+ MutexReadLock lock(&ctx->lock);
+ if (ctx->tlsext_ticket_key_current &&
+ (ctx->tlsext_ticket_key_current->next_rotation_tv_sec == 0 ||
+ ctx->tlsext_ticket_key_current->next_rotation_tv_sec > now.tv_sec) &&
+ (!ctx->tlsext_ticket_key_prev ||
+ ctx->tlsext_ticket_key_prev->next_rotation_tv_sec > now.tv_sec)) {
+ return 1;
+ }
+ }
+
+ MutexWriteLock lock(&ctx->lock);
+ if (!ctx->tlsext_ticket_key_current ||
+ (ctx->tlsext_ticket_key_current->next_rotation_tv_sec != 0 &&
+ ctx->tlsext_ticket_key_current->next_rotation_tv_sec <= now.tv_sec)) {
+ /* The current key has not been initialized or it is expired. */
+ auto new_key = bssl::MakeUnique<struct tlsext_ticket_key>();
+ if (!new_key) {
+ return 0;
+ }
+ OPENSSL_memset(new_key.get(), 0, sizeof(struct tlsext_ticket_key));
+ if (ctx->tlsext_ticket_key_current) {
+ /* The current key expired. Rotate it to prev and bump up its rotation
+ * timestamp. Note that even with the new rotation time it may still be
+ * expired and get droppped below. */
+ ctx->tlsext_ticket_key_current->next_rotation_tv_sec +=
+ SSL_DEFAULT_TICKET_KEY_ROTATION_INTERVAL;
+ OPENSSL_free(ctx->tlsext_ticket_key_prev);
+ ctx->tlsext_ticket_key_prev = ctx->tlsext_ticket_key_current;
+ }
+ ctx->tlsext_ticket_key_current = new_key.release();
+ RAND_bytes(ctx->tlsext_ticket_key_current->name, 16);
+ RAND_bytes(ctx->tlsext_ticket_key_current->hmac_key, 16);
+ RAND_bytes(ctx->tlsext_ticket_key_current->aes_key, 16);
+ ctx->tlsext_ticket_key_current->next_rotation_tv_sec =
+ now.tv_sec + SSL_DEFAULT_TICKET_KEY_ROTATION_INTERVAL;
+ }
+
+ /* Drop an expired prev key. */
+ if (ctx->tlsext_ticket_key_prev &&
+ ctx->tlsext_ticket_key_prev->next_rotation_tv_sec <= now.tv_sec) {
+ OPENSSL_free(ctx->tlsext_ticket_key_prev);
+ ctx->tlsext_ticket_key_prev = nullptr;
+ }
+
+ return 1;
+}
+
static int ssl_encrypt_ticket_with_cipher_ctx(SSL *ssl, CBB *out,
const uint8_t *session_buf,
size_t session_len) {
@@ -464,14 +508,19 @@ static int ssl_encrypt_ticket_with_cipher_ctx(SSL *ssl, CBB *out,
return 0;
}
} else {
+ /* Rotate ticket key if necessary. */
+ if (!ssl_ctx_rotate_ticket_encryption_key(tctx)) {
+ return 0;
+ }
+ MutexReadLock lock(&tctx->lock);
if (!RAND_bytes(iv, 16) ||
!EVP_EncryptInit_ex(ctx.get(), EVP_aes_128_cbc(), NULL,
- tctx->tlsext_tick_aes_key, iv) ||
- !HMAC_Init_ex(hctx.get(), tctx->tlsext_tick_hmac_key, 16,
+ tctx->tlsext_ticket_key_current->aes_key, iv) ||
+ !HMAC_Init_ex(hctx.get(), tctx->tlsext_ticket_key_current->hmac_key, 16,
tlsext_tick_md(), NULL)) {
return 0;
}
- OPENSSL_memcpy(key_name, tctx->tlsext_tick_key_name, 16);
+ OPENSSL_memcpy(key_name, tctx->tlsext_ticket_key_current->name, 16);
}
uint8_t *ptr;
@@ -840,8 +889,8 @@ void SSL_SESSION_free(SSL_SESSION *session) {
session->x509_method->session_clear(session);
OPENSSL_free(session->tlsext_hostname);
OPENSSL_free(session->tlsext_tick);
- OPENSSL_free(session->tlsext_signed_cert_timestamp_list);
- OPENSSL_free(session->ocsp_response);
+ CRYPTO_BUFFER_free(session->signed_cert_timestamp_list);
+ CRYPTO_BUFFER_free(session->ocsp_response);
OPENSSL_free(session->psk_identity);
OPENSSL_free(session->early_alpn);
OPENSSL_cleanse(session, sizeof(*session));