summaryrefslogtreecommitdiff
path: root/src/ssl/t1_lib.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/ssl/t1_lib.cc')
-rw-r--r--src/ssl/t1_lib.cc152
1 files changed, 95 insertions, 57 deletions
diff --git a/src/ssl/t1_lib.cc b/src/ssl/t1_lib.cc
index 39f4be62..e50710a5 100644
--- a/src/ssl/t1_lib.cc
+++ b/src/ssl/t1_lib.cc
@@ -1327,11 +1327,14 @@ static int ext_sct_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
* requirement, so tolerate this.
*
* TODO(davidben): Enforce this anyway. */
- if (!ssl->s3->session_reused &&
- !CBS_stow(contents, &hs->new_session->tlsext_signed_cert_timestamp_list,
- &hs->new_session->tlsext_signed_cert_timestamp_list_length)) {
- *out_alert = SSL_AD_INTERNAL_ERROR;
- return 0;
+ if (!ssl->s3->session_reused) {
+ CRYPTO_BUFFER_free(hs->new_session->signed_cert_timestamp_list);
+ hs->new_session->signed_cert_timestamp_list =
+ CRYPTO_BUFFER_new_from_CBS(contents, ssl->ctx->pool);
+ if (hs->new_session->signed_cert_timestamp_list == nullptr) {
+ *out_alert = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
}
return 1;
@@ -2795,7 +2798,6 @@ static int ssl_scan_clienthello_tlsext(SSL_HANDSHAKE *hs,
hs->extensions.received = 0;
hs->custom_extensions.received = 0;
-
CBS extensions;
CBS_init(&extensions, client_hello->extensions, client_hello->extensions_len);
while (CBS_len(&extensions) != 0) {
@@ -2919,6 +2921,7 @@ static int ssl_scan_serverhello_tlsext(SSL_HANDSHAKE *hs, CBS *cbs,
tls_extension_find(&ext_index, type);
if (ext == NULL) {
+ hs->received_custom_extension = 1;
if (!custom_ext_parse_serverhello(hs, out_alert, type, &extension)) {
return 0;
}
@@ -3004,60 +3007,20 @@ int ssl_parse_serverhello_tlsext(SSL_HANDSHAKE *hs, CBS *cbs) {
return 1;
}
-static enum ssl_ticket_aead_result_t
-ssl_decrypt_ticket_with_cipher_ctx(SSL *ssl, uint8_t **out, size_t *out_len,
- int *out_renew_ticket, const uint8_t *ticket,
- size_t ticket_len) {
- const SSL_CTX *const ssl_ctx = ssl->session_ctx;
-
- ScopedHMAC_CTX hmac_ctx;
- ScopedEVP_CIPHER_CTX cipher_ctx;
-
- /* Ensure there is room for the key name and the largest IV
- * |tlsext_ticket_key_cb| may try to consume. The real limit may be lower, but
- * the maximum IV length should be well under the minimum size for the
- * session material and HMAC. */
- if (ticket_len < SSL_TICKET_KEY_NAME_LEN + EVP_MAX_IV_LENGTH) {
- return ssl_ticket_aead_ignore_ticket;
- }
- const uint8_t *iv = ticket + SSL_TICKET_KEY_NAME_LEN;
-
- if (ssl_ctx->tlsext_ticket_key_cb != NULL) {
- int cb_ret = ssl_ctx->tlsext_ticket_key_cb(
- ssl, (uint8_t *)ticket /* name */, (uint8_t *)iv, cipher_ctx.get(),
- hmac_ctx.get(), 0 /* decrypt */);
- if (cb_ret < 0) {
- return ssl_ticket_aead_error;
- } else if (cb_ret == 0) {
- return ssl_ticket_aead_ignore_ticket;
- } else if (cb_ret == 2) {
- *out_renew_ticket = 1;
- }
- } else {
- /* Check the key name matches. */
- if (OPENSSL_memcmp(ticket, ssl_ctx->tlsext_tick_key_name,
- SSL_TICKET_KEY_NAME_LEN) != 0) {
- return ssl_ticket_aead_ignore_ticket;
- }
- if (!HMAC_Init_ex(hmac_ctx.get(), ssl_ctx->tlsext_tick_hmac_key,
- sizeof(ssl_ctx->tlsext_tick_hmac_key), tlsext_tick_md(),
- NULL) ||
- !EVP_DecryptInit_ex(cipher_ctx.get(), EVP_aes_128_cbc(), NULL,
- ssl_ctx->tlsext_tick_aes_key, iv)) {
- return ssl_ticket_aead_error;
- }
- }
- size_t iv_len = EVP_CIPHER_CTX_iv_length(cipher_ctx.get());
+static enum ssl_ticket_aead_result_t decrypt_ticket_with_cipher_ctx(
+ uint8_t **out, size_t *out_len, EVP_CIPHER_CTX *cipher_ctx,
+ HMAC_CTX *hmac_ctx, const uint8_t *ticket, size_t ticket_len) {
+ size_t iv_len = EVP_CIPHER_CTX_iv_length(cipher_ctx);
/* Check the MAC at the end of the ticket. */
uint8_t mac[EVP_MAX_MD_SIZE];
- size_t mac_len = HMAC_size(hmac_ctx.get());
+ size_t mac_len = HMAC_size(hmac_ctx);
if (ticket_len < SSL_TICKET_KEY_NAME_LEN + iv_len + 1 + mac_len) {
/* The ticket must be large enough for key name, IV, data, and MAC. */
return ssl_ticket_aead_ignore_ticket;
}
- HMAC_Update(hmac_ctx.get(), ticket, ticket_len - mac_len);
- HMAC_Final(hmac_ctx.get(), mac, NULL);
+ HMAC_Update(hmac_ctx, ticket, ticket_len - mac_len);
+ HMAC_Final(hmac_ctx, mac, NULL);
int mac_ok =
CRYPTO_memcmp(mac, ticket + (ticket_len - mac_len), mac_len) == 0;
#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
@@ -3084,9 +3047,9 @@ ssl_decrypt_ticket_with_cipher_ctx(SSL *ssl, uint8_t **out, size_t *out_len,
return ssl_ticket_aead_ignore_ticket;
}
int len1, len2;
- if (!EVP_DecryptUpdate(cipher_ctx.get(), plaintext.get(), &len1, ciphertext,
+ if (!EVP_DecryptUpdate(cipher_ctx, plaintext.get(), &len1, ciphertext,
(int)ciphertext_len) ||
- !EVP_DecryptFinal_ex(cipher_ctx.get(), plaintext.get() + len1, &len2)) {
+ !EVP_DecryptFinal_ex(cipher_ctx, plaintext.get() + len1, &len2)) {
ERR_clear_error();
return ssl_ticket_aead_ignore_ticket;
}
@@ -3098,6 +3061,69 @@ ssl_decrypt_ticket_with_cipher_ctx(SSL *ssl, uint8_t **out, size_t *out_len,
return ssl_ticket_aead_success;
}
+static enum ssl_ticket_aead_result_t ssl_decrypt_ticket_with_cb(
+ SSL *ssl, uint8_t **out, size_t *out_len, int *out_renew_ticket,
+ const uint8_t *ticket, size_t ticket_len) {
+ assert(ticket_len >= SSL_TICKET_KEY_NAME_LEN + EVP_MAX_IV_LENGTH);
+ ScopedEVP_CIPHER_CTX cipher_ctx;
+ ScopedHMAC_CTX hmac_ctx;
+ const uint8_t *iv = ticket + SSL_TICKET_KEY_NAME_LEN;
+ int cb_ret = ssl->session_ctx->tlsext_ticket_key_cb(
+ ssl, (uint8_t *)ticket /* name */, (uint8_t *)iv, cipher_ctx.get(),
+ hmac_ctx.get(), 0 /* decrypt */);
+ if (cb_ret < 0) {
+ return ssl_ticket_aead_error;
+ } else if (cb_ret == 0) {
+ return ssl_ticket_aead_ignore_ticket;
+ } else if (cb_ret == 2) {
+ *out_renew_ticket = 1;
+ } else {
+ assert(cb_ret == 1);
+ }
+ return decrypt_ticket_with_cipher_ctx(out, out_len, cipher_ctx.get(),
+ hmac_ctx.get(), ticket, ticket_len);
+}
+
+static enum ssl_ticket_aead_result_t ssl_decrypt_ticket_with_ticket_keys(
+ SSL *ssl, uint8_t **out, size_t *out_len, const uint8_t *ticket,
+ size_t ticket_len) {
+ assert(ticket_len >= SSL_TICKET_KEY_NAME_LEN + EVP_MAX_IV_LENGTH);
+ SSL_CTX *ctx = ssl->session_ctx;
+
+ /* Rotate the ticket key if necessary. */
+ if (!ssl_ctx_rotate_ticket_encryption_key(ctx)) {
+ return ssl_ticket_aead_error;
+ }
+
+ /* Pick the matching ticket key and decrypt. */
+ ScopedEVP_CIPHER_CTX cipher_ctx;
+ ScopedHMAC_CTX hmac_ctx;
+ {
+ MutexReadLock lock(&ctx->lock);
+ const tlsext_ticket_key *key;
+ if (ctx->tlsext_ticket_key_current &&
+ !OPENSSL_memcmp(ctx->tlsext_ticket_key_current->name, ticket,
+ SSL_TICKET_KEY_NAME_LEN)) {
+ key = ctx->tlsext_ticket_key_current;
+ } else if (ctx->tlsext_ticket_key_prev &&
+ !OPENSSL_memcmp(ctx->tlsext_ticket_key_prev->name, ticket,
+ SSL_TICKET_KEY_NAME_LEN)) {
+ key = ctx->tlsext_ticket_key_prev;
+ } else {
+ return ssl_ticket_aead_ignore_ticket;
+ }
+ const uint8_t *iv = ticket + SSL_TICKET_KEY_NAME_LEN;
+ if (!HMAC_Init_ex(hmac_ctx.get(), key->hmac_key, sizeof(key->hmac_key),
+ tlsext_tick_md(), NULL) ||
+ !EVP_DecryptInit_ex(cipher_ctx.get(), EVP_aes_128_cbc(), NULL,
+ key->aes_key, iv)) {
+ return ssl_ticket_aead_error;
+ }
+ }
+ return decrypt_ticket_with_cipher_ctx(out, out_len, cipher_ctx.get(),
+ hmac_ctx.get(), ticket, ticket_len);
+}
+
static enum ssl_ticket_aead_result_t ssl_decrypt_ticket_with_method(
SSL *ssl, uint8_t **out, size_t *out_len, int *out_renew_ticket,
const uint8_t *ticket, size_t ticket_len) {
@@ -3141,8 +3167,20 @@ enum ssl_ticket_aead_result_t ssl_process_ticket(
result = ssl_decrypt_ticket_with_method(
ssl, &plaintext, &plaintext_len, out_renew_ticket, ticket, ticket_len);
} else {
- result = ssl_decrypt_ticket_with_cipher_ctx(
- ssl, &plaintext, &plaintext_len, out_renew_ticket, ticket, ticket_len);
+ /* Ensure there is room for the key name and the largest IV
+ * |tlsext_ticket_key_cb| may try to consume. The real limit may be lower,
+ * but the maximum IV length should be well under the minimum size for the
+ * session material and HMAC. */
+ if (ticket_len < SSL_TICKET_KEY_NAME_LEN + EVP_MAX_IV_LENGTH) {
+ return ssl_ticket_aead_ignore_ticket;
+ }
+ if (ssl->session_ctx->tlsext_ticket_key_cb != NULL) {
+ result = ssl_decrypt_ticket_with_cb(ssl, &plaintext, &plaintext_len,
+ out_renew_ticket, ticket, ticket_len);
+ } else {
+ result = ssl_decrypt_ticket_with_ticket_keys(
+ ssl, &plaintext, &plaintext_len, ticket, ticket_len);
+ }
}
if (result != ssl_ticket_aead_success) {