Move new_cipher and new_session to SSL_HANDSHAKE.
This lets us trim another two pointers of per-connection state.
Change-Id: I2145d529bc25b7e24a921d01e82ee99f2c98867c
Reviewed-on: https://boringssl-review.googlesource.com/13804
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/ssl/handshake_server.c b/ssl/handshake_server.c
index d3a32ef..fdf78e4 100644
--- a/ssl/handshake_server.c
+++ b/ssl/handshake_server.c
@@ -263,7 +263,7 @@
break;
case SSL3_ST_SW_CERT_A:
- if (ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
+ if (ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
ret = ssl3_send_server_certificate(hs);
if (ret <= 0) {
goto end;
@@ -284,10 +284,10 @@
case SSL3_ST_SW_KEY_EXCH_A:
case SSL3_ST_SW_KEY_EXCH_B:
- alg_a = ssl->s3->tmp.new_cipher->algorithm_auth;
+ alg_a = hs->new_cipher->algorithm_auth;
/* PSK ciphers send ServerKeyExchange if there is an identity hint. */
- if (ssl_cipher_requires_server_key_exchange(ssl->s3->tmp.new_cipher) ||
+ if (ssl_cipher_requires_server_key_exchange(hs->new_cipher) ||
((alg_a & SSL_aPSK) && ssl->psk_identity_hint)) {
ret = ssl3_send_server_key_exchange(hs);
if (ret <= 0) {
@@ -393,7 +393,7 @@
}
/* If this is a full handshake with ChannelID then record the handshake
- * hashes in |ssl->s3->new_session| in case we need them to verify a
+ * hashes in |hs->new_session| in case we need them to verify a
* ChannelID signature on a resumption of this session in the future. */
if (ssl->session == NULL && ssl->s3->tlsext_channel_id_valid) {
ret = tls1_record_handshake_hashes_for_channel_id(hs);
@@ -461,12 +461,11 @@
/* If we aren't retaining peer certificates then we can discard it
* now. */
- if (ssl->s3->new_session != NULL &&
+ if (hs->new_session != NULL &&
ssl->retain_only_sha256_of_client_certs) {
- sk_CRYPTO_BUFFER_pop_free(ssl->s3->new_session->certs,
- CRYPTO_BUFFER_free);
- ssl->s3->new_session->certs = NULL;
- ssl->ctx->x509_method->session_clear(ssl->s3->new_session);
+ sk_CRYPTO_BUFFER_pop_free(hs->new_session->certs, CRYPTO_BUFFER_free);
+ hs->new_session->certs = NULL;
+ ssl->ctx->x509_method->session_clear(hs->new_session);
}
SSL_SESSION_free(ssl->s3->established_session);
@@ -474,9 +473,9 @@
SSL_SESSION_up_ref(ssl->session);
ssl->s3->established_session = ssl->session;
} else {
- ssl->s3->established_session = ssl->s3->new_session;
+ ssl->s3->established_session = hs->new_session;
ssl->s3->established_session->not_resumable = 0;
- ssl->s3->new_session = NULL;
+ hs->new_session = NULL;
}
if (hs->v2_clienthello) {
@@ -897,9 +896,9 @@
/* Negotiate the cipher suite. This must be done after |cert_cb| so the
* certificate is finalized. */
- ssl->s3->tmp.new_cipher =
+ hs->new_cipher =
ssl3_choose_cipher(hs, &client_hello, ssl_get_cipher_preferences(ssl));
- if (ssl->s3->tmp.new_cipher == NULL) {
+ if (hs->new_cipher == NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_CIPHER);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
return -1;
@@ -943,7 +942,7 @@
goto f_err;
}
- if (!ssl_session_is_resumable(ssl, session) ||
+ if (!ssl_session_is_resumable(hs, session) ||
/* If the client offers the EMS extension, but the previous session
* didn't use it, then negotiate a new session. */
ssl->s3->tmp.extended_master_secret !=
@@ -968,7 +967,7 @@
/* Clear the session ID if we want the session to be single-use. */
if (!(ssl->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)) {
- ssl->s3->new_session->session_id_length = 0;
+ hs->new_session->session_id_length = 0;
}
}
@@ -981,13 +980,13 @@
}
if (ssl->session == NULL) {
- ssl->s3->new_session->cipher = ssl->s3->tmp.new_cipher;
+ hs->new_session->cipher = hs->new_cipher;
/* On new sessions, stash the SNI value in the session. */
if (hs->hostname != NULL) {
- OPENSSL_free(ssl->s3->new_session->tlsext_hostname);
- ssl->s3->new_session->tlsext_hostname = BUF_strdup(hs->hostname);
- if (ssl->s3->new_session->tlsext_hostname == NULL) {
+ OPENSSL_free(hs->new_session->tlsext_hostname);
+ hs->new_session->tlsext_hostname = BUF_strdup(hs->hostname);
+ if (hs->new_session->tlsext_hostname == NULL) {
al = SSL_AD_INTERNAL_ERROR;
goto f_err;
}
@@ -1001,14 +1000,14 @@
hs->cert_request = 0;
}
/* CertificateRequest may only be sent in certificate-based ciphers. */
- if (!ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
+ if (!ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
hs->cert_request = 0;
}
if (!hs->cert_request) {
/* OpenSSL returns X509_V_OK when no certificates are requested. This is
* classed by them as a bug, but it's assumed by at least NGINX. */
- ssl->s3->new_session->verify_result = X509_V_OK;
+ hs->new_session->verify_result = X509_V_OK;
}
}
@@ -1021,7 +1020,7 @@
/* Now that all parameters are known, initialize the handshake hash and hash
* the ClientHello. */
if (!SSL_TRANSCRIPT_init_hash(&hs->transcript, ssl3_protocol_version(ssl),
- ssl->s3->tmp.new_cipher->algorithm_prf) ||
+ hs->new_cipher->algorithm_prf) ||
!ssl_hash_current_message(hs)) {
goto f_err;
}
@@ -1049,7 +1048,7 @@
/* We only accept ChannelIDs on connections with ECDHE in order to avoid a
* known attack while we fix ChannelID itself. */
if (ssl->s3->tlsext_channel_id_valid &&
- (ssl->s3->tmp.new_cipher->algorithm_mkey & SSL_kECDHE) == 0) {
+ (hs->new_cipher->algorithm_mkey & SSL_kECDHE) == 0) {
ssl->s3->tlsext_channel_id_valid = 0;
}
@@ -1074,7 +1073,7 @@
/* TODO(davidben): Implement the TLS 1.1 and 1.2 downgrade sentinels once TLS
* 1.3 is finalized and we are not implementing a draft version. */
- const SSL_SESSION *session = ssl->s3->new_session;
+ const SSL_SESSION *session = hs->new_session;
if (ssl->session != NULL) {
session = ssl->session;
}
@@ -1086,7 +1085,7 @@
!CBB_add_u8_length_prefixed(&body, &session_id) ||
!CBB_add_bytes(&session_id, session->session_id,
session->session_id_length) ||
- !CBB_add_u16(&body, ssl_cipher_get_value(ssl->s3->tmp.new_cipher)) ||
+ !CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher)) ||
!CBB_add_u8(&body, 0 /* no compression */) ||
!ssl_add_serverhello_tlsext(hs, &body) ||
!ssl_add_message_cbb(ssl, &cbb)) {
@@ -1137,8 +1136,8 @@
/* Put together the parameters. */
if (hs->state == SSL3_ST_SW_KEY_EXCH_A) {
- uint32_t alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey;
- uint32_t alg_a = ssl->s3->tmp.new_cipher->algorithm_auth;
+ uint32_t alg_k = hs->new_cipher->algorithm_mkey;
+ uint32_t alg_a = hs->new_cipher->algorithm_auth;
/* Pre-allocate enough room to comfortably fit an ECDHE public key. */
if (!CBB_init(&cbb, 128)) {
@@ -1191,7 +1190,7 @@
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
goto err;
}
- ssl->s3->new_session->group_id = group_id;
+ hs->new_session->group_id = group_id;
/* Set up ECDH, generate a key, and emit the public half. */
if (!SSL_ECDH_CTX_init(&hs->ecdh_ctx, group_id) ||
@@ -1219,7 +1218,7 @@
}
/* Add a signature. */
- if (ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
+ if (ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
if (!ssl_has_private_key(ssl)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
goto err;
@@ -1416,7 +1415,7 @@
/* OpenSSL returns X509_V_OK when no certificates are received. This is
* classed by them as a bug, but it's assumed by at least NGINX. */
- ssl->s3->new_session->verify_result = X509_V_OK;
+ hs->new_session->verify_result = X509_V_OK;
ssl->s3->tmp.reuse_message = 1;
return 1;
}
@@ -1433,29 +1432,28 @@
CBS certificate_msg;
CBS_init(&certificate_msg, ssl->init_msg, ssl->init_num);
- sk_CRYPTO_BUFFER_pop_free(ssl->s3->new_session->certs, CRYPTO_BUFFER_free);
+ sk_CRYPTO_BUFFER_pop_free(hs->new_session->certs, CRYPTO_BUFFER_free);
EVP_PKEY_free(hs->peer_pubkey);
hs->peer_pubkey = NULL;
uint8_t alert = SSL_AD_DECODE_ERROR;
- ssl->s3->new_session->certs =
- ssl_parse_cert_chain(&alert, &hs->peer_pubkey,
- ssl->retain_only_sha256_of_client_certs
- ? ssl->s3->new_session->peer_sha256
- : NULL,
- &certificate_msg, ssl->ctx->pool);
- if (ssl->s3->new_session->certs == NULL) {
+ hs->new_session->certs = ssl_parse_cert_chain(
+ &alert, &hs->peer_pubkey,
+ ssl->retain_only_sha256_of_client_certs ? hs->new_session->peer_sha256
+ : NULL,
+ &certificate_msg, ssl->ctx->pool);
+ if (hs->new_session->certs == NULL) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return -1;
}
if (CBS_len(&certificate_msg) != 0 ||
- !ssl->ctx->x509_method->session_cache_objects(ssl->s3->new_session)) {
+ !ssl->ctx->x509_method->session_cache_objects(hs->new_session)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return -1;
}
- if (sk_CRYPTO_BUFFER_num(ssl->s3->new_session->certs) == 0) {
+ if (sk_CRYPTO_BUFFER_num(hs->new_session->certs) == 0) {
/* No client certificate so the handshake buffer may be discarded. */
SSL_TRANSCRIPT_free_buffer(&hs->transcript);
@@ -1476,17 +1474,17 @@
/* OpenSSL returns X509_V_OK when no certificates are received. This is
* classed by them as a bug, but it's assumed by at least NGINX. */
- ssl->s3->new_session->verify_result = X509_V_OK;
+ hs->new_session->verify_result = X509_V_OK;
return 1;
}
/* The hash will have been filled in. */
if (ssl->retain_only_sha256_of_client_certs) {
- ssl->s3->new_session->peer_sha256_valid = 1;
+ hs->new_session->peer_sha256_valid = 1;
}
- if (!ssl_verify_cert_chain(ssl, &ssl->s3->new_session->verify_result,
- ssl->s3->new_session->x509_chain)) {
+ if (!ssl_verify_cert_chain(ssl, &hs->new_session->verify_result,
+ hs->new_session->x509_chain)) {
return -1;
}
return 1;
@@ -1518,8 +1516,8 @@
}
CBS_init(&client_key_exchange, ssl->init_msg, ssl->init_num);
- alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey;
- alg_a = ssl->s3->tmp.new_cipher->algorithm_auth;
+ alg_k = hs->new_cipher->algorithm_mkey;
+ alg_a = hs->new_cipher->algorithm_auth;
/* If using a PSK key exchange, prepare the pre-shared key. */
if (alg_a & SSL_aPSK) {
@@ -1547,15 +1545,15 @@
goto f_err;
}
- if (!CBS_strdup(&psk_identity, &ssl->s3->new_session->psk_identity)) {
+ if (!CBS_strdup(&psk_identity, &hs->new_session->psk_identity)) {
al = SSL_AD_INTERNAL_ERROR;
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto f_err;
}
/* Look up the key for the identity. */
- psk_len = ssl->psk_server_callback(ssl, ssl->s3->new_session->psk_identity,
- psk, sizeof(psk));
+ psk_len = ssl->psk_server_callback(ssl, hs->new_session->psk_identity, psk,
+ sizeof(psk));
if (psk_len > PSK_MAX_PSK_LEN) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
al = SSL_AD_INTERNAL_ERROR;
@@ -1740,14 +1738,12 @@
}
/* Compute the master secret */
- ssl->s3->new_session->master_key_length =
- tls1_generate_master_secret(hs, ssl->s3->new_session->master_key,
- premaster_secret, premaster_secret_len);
- if (ssl->s3->new_session->master_key_length == 0) {
+ hs->new_session->master_key_length = tls1_generate_master_secret(
+ hs, hs->new_session->master_key, premaster_secret, premaster_secret_len);
+ if (hs->new_session->master_key_length == 0) {
goto err;
}
- ssl->s3->new_session->extended_master_secret =
- ssl->s3->tmp.extended_master_secret;
+ hs->new_session->extended_master_secret = ssl->s3->tmp.extended_master_secret;
OPENSSL_cleanse(premaster_secret, premaster_secret_len);
OPENSSL_free(premaster_secret);
@@ -1800,7 +1796,7 @@
if (!tls12_check_peer_sigalg(ssl, &al, signature_algorithm)) {
goto f_err;
}
- ssl->s3->new_session->peer_signature_algorithm = signature_algorithm;
+ hs->new_session->peer_signature_algorithm = signature_algorithm;
} else if (hs->peer_pubkey->type == EVP_PKEY_RSA) {
signature_algorithm = SSL_SIGN_RSA_PKCS1_MD5_SHA1;
} else if (hs->peer_pubkey->type == EVP_PKEY_EC) {
@@ -1826,7 +1822,7 @@
uint8_t digest[EVP_MAX_MD_SIZE];
size_t digest_len;
if (!SSL_TRANSCRIPT_ssl3_cert_verify_hash(&hs->transcript, digest,
- &digest_len, ssl->s3->new_session,
+ &digest_len, hs->new_session,
signature_algorithm)) {
goto err;
}
@@ -1923,8 +1919,8 @@
SSL_SESSION *session_copy = NULL;
if (ssl->session == NULL) {
/* Fix the timeout to measure from the ticket issuance time. */
- ssl_session_rebase_time(ssl, ssl->s3->new_session);
- session = ssl->s3->new_session;
+ ssl_session_rebase_time(ssl, hs->new_session);
+ session = hs->new_session;
} else {
/* We are renewing an existing session. Duplicate the session to adjust the
* timeout. */