SSL_CONFIG: new struct for sheddable handshake configuration.
|SSL_CONFIG| is a container for bits of configuration that are
unneeded after the handshake completes. By default it is retained for
the life of the |SSL|, but it may be shed at the caller's option by
calling SSL_set_shed_handshake_config(). This is incompatible with
renegotiation, and with SSL_clear().
|SSL_CONFIG| is reachable by |ssl->config| and by |hs->config|. The
latter is always non-NULL. To avoid null checks, I've changed the
signature of a number of functions from |SSL*| arguments to
|SSL_HANDSHAKE*| arguments.
When configuration has been shed, setters that touch |SSL_CONFIG|
return an error value if that is possible. Setters that return |void|
do nothing.
Getters that request |SSL_CONFIG| values will fail with an |assert| if
the configuration has been shed. When asserts are compiled out, they
will return an error value.
The aim of this commit is to simplify analysis of split-handshakes by
making it obvious that some bits of state have no effects beyond the
handshake. It also cuts down on memory usage.
Of note: |SSL_CTX| is still reachable after the configuration has been
shed, and a couple things need to be retained only for the sake of
post-handshake hooks. Perhaps these can be fixed in time.
Change-Id: Idf09642e0518945b81a1e9fcd7331cc9cf7cc2d6
Bug: 123
Reviewed-on: https://boringssl-review.googlesource.com/27644
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/ssl/handshake_client.cc b/ssl/handshake_client.cc
index fbef2e1..e9b0eed 100644
--- a/ssl/handshake_client.cc
+++ b/ssl/handshake_client.cc
@@ -199,13 +199,13 @@
// ssl_get_client_disabled sets |*out_mask_a| and |*out_mask_k| to masks of
// disabled algorithms.
-static void ssl_get_client_disabled(SSL *ssl, uint32_t *out_mask_a,
+static void ssl_get_client_disabled(SSL_HANDSHAKE *hs, uint32_t *out_mask_a,
uint32_t *out_mask_k) {
*out_mask_a = 0;
*out_mask_k = 0;
// PSK requires a client callback.
- if (ssl->psk_client_callback == NULL) {
+ if (hs->config->psk_client_callback == NULL) {
*out_mask_a |= SSL_aPSK;
*out_mask_k |= SSL_kPSK;
}
@@ -214,7 +214,7 @@
static int ssl_write_client_cipher_list(SSL_HANDSHAKE *hs, CBB *out) {
SSL *const ssl = hs->ssl;
uint32_t mask_a, mask_k;
- ssl_get_client_disabled(ssl, &mask_a, &mask_k);
+ ssl_get_client_disabled(hs, &mask_a, &mask_k);
CBB child;
if (!CBB_add_u16_length_prefixed(out, &child)) {
@@ -390,7 +390,7 @@
ssl->s3->session_reused = false;
// Freeze the version range.
- if (!ssl_get_version_range(ssl, &hs->min_version, &hs->max_version)) {
+ if (!ssl_get_version_range(hs, &hs->min_version, &hs->max_version)) {
return ssl_hs_error;
}
@@ -659,7 +659,7 @@
// The cipher must be allowed in the selected version and enabled.
uint32_t mask_a, mask_k;
- ssl_get_client_disabled(ssl, &mask_a, &mask_k);
+ ssl_get_client_disabled(hs, &mask_a, &mask_k);
if ((cipher->algorithm_mkey & mask_k) || (cipher->algorithm_auth & mask_a) ||
SSL_CIPHER_get_min_version(cipher) > ssl_protocol_version(ssl) ||
SSL_CIPHER_get_max_version(cipher) < ssl_protocol_version(ssl) ||
@@ -680,7 +680,7 @@
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
return ssl_hs_error;
}
- if (!ssl_session_is_context_valid(ssl, ssl->session)) {
+ if (!ssl_session_is_context_valid(hs, ssl->session)) {
// This is actually a client application bug.
OPENSSL_PUT_ERROR(SSL,
SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
@@ -970,7 +970,7 @@
hs->new_session->group_id = group_id;
// Ensure the group is consistent with preferences.
- if (!tls1_check_group_id(ssl, group_id)) {
+ if (!tls1_check_group_id(hs, group_id)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
return ssl_hs_error;
@@ -1176,8 +1176,8 @@
}
// Call cert_cb to update the certificate.
- if (ssl->cert->cert_cb != NULL) {
- int rv = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg);
+ if (hs->config->cert->cert_cb != NULL) {
+ int rv = hs->config->cert->cert_cb(ssl, hs->config->cert->cert_cb_arg);
if (rv == 0) {
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_CB_ERROR);
@@ -1189,7 +1189,7 @@
}
}
- if (!ssl_has_certificate(ssl)) {
+ if (!ssl_has_certificate(hs->config)) {
// Without a client certificate, the handshake buffer may be released.
hs->transcript.FreeBuffer();
@@ -1205,7 +1205,7 @@
}
if (!ssl_on_certificate_selected(hs) ||
- !ssl_output_cert_chain(ssl)) {
+ !ssl_output_cert_chain(hs)) {
return ssl_hs_error;
}
@@ -1234,16 +1234,16 @@
unsigned psk_len = 0;
uint8_t psk[PSK_MAX_PSK_LEN];
if (alg_a & SSL_aPSK) {
- if (ssl->psk_client_callback == NULL) {
+ if (hs->config->psk_client_callback == NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_NO_CLIENT_CB);
return ssl_hs_error;
}
char identity[PSK_MAX_IDENTITY_LEN + 1];
OPENSSL_memset(identity, 0, sizeof(identity));
- psk_len =
- ssl->psk_client_callback(ssl, hs->peer_psk_identity_hint.get(),
- identity, sizeof(identity), psk, sizeof(psk));
+ psk_len = hs->config->psk_client_callback(
+ ssl, hs->peer_psk_identity_hint.get(), identity, sizeof(identity), psk,
+ sizeof(psk));
if (psk_len == 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
@@ -1373,12 +1373,12 @@
static enum ssl_hs_wait_t do_send_client_certificate_verify(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- if (!hs->cert_request || !ssl_has_certificate(ssl)) {
+ if (!hs->cert_request || !ssl_has_certificate(hs->config)) {
hs->state = state_send_client_finished;
return ssl_hs_ok;
}
- assert(ssl_has_private_key(ssl));
+ assert(ssl_has_private_key(hs->config));
ScopedCBB cbb;
CBB body, child;
if (!ssl->method->init_message(ssl, cbb.get(), &body,
@@ -1410,7 +1410,7 @@
// The SSL3 construction for CertificateVerify does not decompose into a
// single final digest and signature, and must be special-cased.
if (ssl_protocol_version(ssl) == SSL3_VERSION) {
- if (ssl->cert->key_method != NULL) {
+ if (hs->config->cert->key_method != NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY);
return ssl_hs_error;
}
@@ -1423,7 +1423,7 @@
}
UniquePtr<EVP_PKEY_CTX> pctx(
- EVP_PKEY_CTX_new(ssl->cert->privatekey.get(), nullptr));
+ EVP_PKEY_CTX_new(hs->config->cert->privatekey.get(), nullptr));
if (!pctx ||
!EVP_PKEY_sign_init(pctx.get()) ||
!EVP_PKEY_sign(pctx.get(), ptr, &sig_len, digest, digest_len)) {
@@ -1459,11 +1459,11 @@
SSL *const ssl = hs->ssl;
// Resolve Channel ID first, before any non-idempotent operations.
if (ssl->s3->tlsext_channel_id_valid) {
- if (!ssl_do_channel_id_callback(ssl)) {
+ if (!ssl_do_channel_id_callback(hs)) {
return ssl_hs_error;
}
- if (ssl->tlsext_channel_id_private == NULL) {
+ if (hs->config->tlsext_channel_id_private == NULL) {
hs->state = state_send_client_finished;
return ssl_hs_channel_id_lookup;
}