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/handoff.cc b/ssl/handoff.cc
index 2cbbaeb..89fca2f 100644
--- a/ssl/handoff.cc
+++ b/ssl/handoff.cc
@@ -55,7 +55,7 @@
return false;
}
- ssl->handoff = false;
+ s3->hs->config->handoff = false;
return true;
}
@@ -94,7 +94,7 @@
s3->hs->transcript.Update(transcript);
s3->is_v2_hello = true;
}
- ssl->handback = true;
+ s3->hs->handback = true;
return true;
}
diff --git a/ssl/handshake.cc b/ssl/handshake.cc
index 00a2cc5..3962618 100644
--- a/ssl/handshake.cc
+++ b/ssl/handshake.cc
@@ -146,7 +146,9 @@
ticket_expected(false),
extended_master_secret(false),
pending_private_key_op(false),
- grease_seeded(false) {
+ grease_seeded(false),
+ handback(false) {
+ assert(ssl);
}
SSL_HANDSHAKE::~SSL_HANDSHAKE() {
@@ -159,6 +161,11 @@
!hs->transcript.Init()) {
return nullptr;
}
+ hs->config = ssl->config;
+ if (!hs->config) {
+ assert(hs->config);
+ return nullptr;
+ }
return hs;
}
@@ -189,7 +196,8 @@
static const size_t kMaxMessageLen = 16384;
if (SSL_in_init(ssl)) {
- if ((!ssl->server || (ssl->verify_mode & SSL_VERIFY_PEER)) &&
+ SSL_CONFIG *config = ssl->config; // SSL_in_init() implies not NULL.
+ if ((!ssl->server || (config->verify_mode & SSL_VERIFY_PEER)) &&
kMaxMessageLen < ssl->max_cert_list) {
return ssl->max_cert_list;
}
@@ -327,15 +335,15 @@
uint8_t alert = SSL_AD_CERTIFICATE_UNKNOWN;
enum ssl_verify_result_t ret;
- if (ssl->custom_verify_callback != nullptr) {
- ret = ssl->custom_verify_callback(ssl, &alert);
+ if (hs->config->custom_verify_callback != nullptr) {
+ ret = hs->config->custom_verify_callback(ssl, &alert);
switch (ret) {
case ssl_verify_ok:
hs->new_session->verify_result = X509_V_OK;
break;
case ssl_verify_invalid:
// If |SSL_VERIFY_NONE|, the error is non-fatal, but we keep the result.
- if (ssl->verify_mode == SSL_VERIFY_NONE) {
+ if (hs->config->verify_mode == SSL_VERIFY_NONE) {
ERR_clear_error();
ret = ssl_verify_ok;
}
@@ -346,7 +354,7 @@
}
} else {
ret = ssl->ctx->x509_method->session_verify_cert_chain(
- hs->new_session.get(), ssl, &alert)
+ hs->new_session.get(), hs, &alert)
? ssl_verify_ok
: ssl_verify_invalid;
}
@@ -475,12 +483,13 @@
return 1;
}
-bool ssl_output_cert_chain(SSL *ssl) {
+bool ssl_output_cert_chain(SSL_HANDSHAKE *hs) {
ScopedCBB cbb;
CBB body;
- if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CERTIFICATE) ||
- !ssl_add_cert_chain(ssl, &body) ||
- !ssl_add_message_cbb(ssl, cbb.get())) {
+ if (!hs->ssl->method->init_message(hs->ssl, cbb.get(), &body,
+ SSL3_MT_CERTIFICATE) ||
+ !ssl_add_cert_chain(hs, &body) ||
+ !ssl_add_message_cbb(hs->ssl, cbb.get())) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return false;
}
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;
}
diff --git a/ssl/handshake_server.cc b/ssl/handshake_server.cc
index 6404cc9..ac8d46b 100644
--- a/ssl/handshake_server.cc
+++ b/ssl/handshake_server.cc
@@ -303,11 +303,10 @@
static void ssl_get_compatible_server_ciphers(SSL_HANDSHAKE *hs,
uint32_t *out_mask_k,
uint32_t *out_mask_a) {
- SSL *const ssl = hs->ssl;
uint32_t mask_k = 0;
uint32_t mask_a = 0;
- if (ssl_has_certificate(ssl)) {
+ if (ssl_has_certificate(hs->config)) {
mask_a |= ssl_cipher_auth_mask_for_key(hs->local_pubkey.get());
if (EVP_PKEY_id(hs->local_pubkey.get()) == EVP_PKEY_RSA) {
mask_k |= SSL_kRSA;
@@ -321,7 +320,7 @@
}
// PSK requires a server callback.
- if (ssl->psk_server_callback != NULL) {
+ if (hs->config->psk_server_callback != NULL) {
mask_k |= SSL_kPSK;
mask_a |= SSL_aPSK;
}
@@ -417,7 +416,7 @@
return ssl_hs_error;
}
- if (ssl->handoff) {
+ if (hs->config->handoff) {
return ssl_hs_handoff;
}
@@ -446,7 +445,7 @@
}
// Freeze the version range after the early callback.
- 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;
}
@@ -494,8 +493,8 @@
}
// Call |cert_cb| to update server certificates if required.
- 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) {
OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_CB_ERROR);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
@@ -523,8 +522,9 @@
// Negotiate the cipher suite. This must be done after |cert_cb| so the
// certificate is finalized.
- hs->new_cipher =
- ssl3_choose_cipher(hs, &client_hello, ssl_get_cipher_preferences(ssl));
+ SSLCipherPreferenceList *prefs =
+ hs->config->cipher_list ? hs->config->cipher_list : ssl->ctx->cipher_list;
+ hs->new_cipher = ssl3_choose_cipher(hs, &client_hello, prefs);
if (hs->new_cipher == NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_CIPHER);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
@@ -562,7 +562,7 @@
UniquePtr<SSL_SESSION> session;
bool tickets_supported = false, renew_ticket = false;
enum ssl_hs_wait_t wait = ssl_get_prev_session(
- ssl, &session, &tickets_supported, &renew_ticket, &client_hello);
+ hs, &session, &tickets_supported, &renew_ticket, &client_hello);
if (wait != ssl_hs_ok) {
return wait;
}
@@ -614,9 +614,9 @@
hs->new_session->cipher = hs->new_cipher;
// Determine whether to request a client certificate.
- hs->cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
+ hs->cert_request = !!(hs->config->verify_mode & SSL_VERIFY_PEER);
// Only request a certificate if Channel ID isn't negotiated.
- if ((ssl->verify_mode & SSL_VERIFY_PEER_IF_NO_OBC) &&
+ if ((hs->config->verify_mode & SSL_VERIFY_PEER_IF_NO_OBC) &&
ssl->s3->tlsext_channel_id_valid) {
hs->cert_request = false;
}
@@ -650,7 +650,7 @@
// Handback includes the whole handshake transcript, so we cannot free the
// transcript buffer in the handback case.
- if (!hs->cert_request && !hs->ssl->handback) {
+ if (!hs->cert_request && !hs->handback) {
hs->transcript.FreeBuffer();
}
@@ -733,12 +733,12 @@
ScopedCBB cbb;
if (ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
- if (!ssl_has_certificate(ssl)) {
+ if (!ssl_has_certificate(hs->config)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
return ssl_hs_error;
}
- if (!ssl_output_cert_chain(ssl)) {
+ if (!ssl_output_cert_chain(hs)) {
return ssl_hs_error;
}
@@ -748,9 +748,10 @@
SSL3_MT_CERTIFICATE_STATUS) ||
!CBB_add_u8(&body, TLSEXT_STATUSTYPE_ocsp) ||
!CBB_add_u24_length_prefixed(&body, &ocsp_response) ||
- !CBB_add_bytes(&ocsp_response,
- CRYPTO_BUFFER_data(ssl->cert->ocsp_response.get()),
- CRYPTO_BUFFER_len(ssl->cert->ocsp_response.get())) ||
+ !CBB_add_bytes(
+ &ocsp_response,
+ CRYPTO_BUFFER_data(hs->config->cert->ocsp_response.get()),
+ CRYPTO_BUFFER_len(hs->config->cert->ocsp_response.get())) ||
!ssl_add_message_cbb(ssl, cbb.get())) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return ssl_hs_error;
@@ -762,8 +763,7 @@
uint32_t alg_k = hs->new_cipher->algorithm_mkey;
uint32_t alg_a = hs->new_cipher->algorithm_auth;
if (ssl_cipher_requires_server_key_exchange(hs->new_cipher) ||
- ((alg_a & SSL_aPSK) && ssl->psk_identity_hint)) {
-
+ ((alg_a & SSL_aPSK) && hs->config->psk_identity_hint)) {
// Pre-allocate enough room to comfortably fit an ECDHE public key. Prepend
// the client and server randoms for the signing transcript.
CBB child;
@@ -775,10 +775,11 @@
// PSK ciphers begin with an identity hint.
if (alg_a & SSL_aPSK) {
- size_t len =
- (ssl->psk_identity_hint == NULL) ? 0 : strlen(ssl->psk_identity_hint);
+ size_t len = (hs->config->psk_identity_hint == NULL)
+ ? 0
+ : strlen(hs->config->psk_identity_hint);
if (!CBB_add_u16_length_prefixed(cbb.get(), &child) ||
- !CBB_add_bytes(&child, (const uint8_t *)ssl->psk_identity_hint,
+ !CBB_add_bytes(&child, (const uint8_t *)hs->config->psk_identity_hint,
len)) {
return ssl_hs_error;
}
@@ -837,7 +838,7 @@
// Add a signature.
if (ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
- if (!ssl_has_private_key(ssl)) {
+ if (!ssl_has_private_key(hs->config)) {
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return ssl_hs_error;
}
@@ -908,7 +909,7 @@
(ssl_protocol_version(ssl) >= TLS1_2_VERSION &&
(!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb) ||
!tls12_add_verify_sigalgs(ssl, &sigalgs_cbb, true /* certs */))) ||
- !ssl_add_client_CA_list(ssl, &body) ||
+ !ssl_add_client_CA_list(hs, &body) ||
!ssl_add_message_cbb(ssl, cbb.get())) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return ssl_hs_error;
@@ -929,8 +930,8 @@
static enum ssl_hs_wait_t do_read_client_certificate(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- if (ssl->handback && hs->new_cipher->algorithm_mkey == SSL_kECDHE) {
- return ssl_hs_handback;
+ if (hs->handback && hs->new_cipher->algorithm_mkey == SSL_kECDHE) {
+ return ssl_hs_handback;
}
if (!hs->cert_request) {
hs->state = state12_verify_client_certificate;
@@ -947,7 +948,7 @@
msg.type == SSL3_MT_CLIENT_KEY_EXCHANGE) {
// In SSL 3.0, the Certificate message is omitted to signal no
// certificate.
- if (ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) {
+ if (hs->config->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
return ssl_hs_error;
@@ -973,7 +974,7 @@
uint8_t alert = SSL_AD_DECODE_ERROR;
UniquePtr<STACK_OF(CRYPTO_BUFFER)> chain;
if (!ssl_parse_cert_chain(&alert, &chain, &hs->peer_pubkey,
- ssl->retain_only_sha256_of_client_certs
+ hs->config->retain_only_sha256_of_client_certs
? hs->new_session->peer_sha256
: NULL,
&certificate_msg, ssl->ctx->pool)) {
@@ -1002,7 +1003,7 @@
return ssl_hs_error;
}
- if (ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) {
+ if (hs->config->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) {
// Fail for TLS only if we required a certificate
OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
@@ -1012,7 +1013,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.
hs->new_session->verify_result = X509_V_OK;
- } else if (ssl->retain_only_sha256_of_client_certs) {
+ } else if (hs->config->retain_only_sha256_of_client_certs) {
// The hash will have been filled in.
hs->new_session->peer_sha256_valid = 1;
}
@@ -1187,7 +1188,7 @@
// For a PSK cipher suite, the actual pre-master secret is combined with the
// pre-shared key.
if (alg_a & SSL_aPSK) {
- if (ssl->psk_server_callback == NULL) {
+ if (hs->config->psk_server_callback == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return ssl_hs_error;
@@ -1195,7 +1196,7 @@
// Look up the key for the identity.
uint8_t psk[PSK_MAX_PSK_LEN];
- unsigned psk_len = ssl->psk_server_callback(
+ unsigned psk_len = hs->config->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);
@@ -1471,7 +1472,7 @@
SSL3_MT_NEW_SESSION_TICKET) ||
!CBB_add_u32(&body, session->timeout) ||
!CBB_add_u16_length_prefixed(&body, &ticket) ||
- !ssl_encrypt_ticket(ssl, &ticket, session) ||
+ !ssl_encrypt_ticket(hs, &ticket, session) ||
!ssl_add_message_cbb(ssl, cbb.get())) {
return ssl_hs_error;
}
@@ -1494,14 +1495,15 @@
static enum ssl_hs_wait_t do_finish_server_handshake(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- if (ssl->handback) {
+ if (hs->handback) {
return ssl_hs_handback;
}
ssl->method->on_handshake_complete(ssl);
// If we aren't retaining peer certificates then we can discard it now.
- if (hs->new_session != NULL && ssl->retain_only_sha256_of_client_certs) {
+ if (hs->new_session != NULL &&
+ hs->config->retain_only_sha256_of_client_certs) {
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.get());
diff --git a/ssl/internal.h b/ssl/internal.h
index b258589..20c060a 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -175,6 +175,7 @@
namespace bssl {
+struct SSL_CONFIG;
struct SSL_HANDSHAKE;
struct SSL_PROTOCOL_METHOD;
@@ -371,7 +372,7 @@
// ssl_get_version_range sets |*out_min_version| and |*out_max_version| to the
// minimum and maximum enabled protocol versions, respectively.
-bool ssl_get_version_range(const SSL *ssl, uint16_t *out_min_version,
+bool ssl_get_version_range(const SSL_HANDSHAKE *hs, uint16_t *out_min_version,
uint16_t *out_max_version);
// ssl_supports_version returns whether |hs| supports |version|.
@@ -908,9 +909,9 @@
// Private key operations.
-// ssl_has_private_key returns one if |ssl| has a private key
-// configured and zero otherwise.
-int ssl_has_private_key(const SSL *ssl);
+// ssl_has_private_key returns one if |cfg| has a private key configured and
+// zero otherwise.
+int ssl_has_private_key(const SSL_CONFIG *cfg);
// ssl_private_key_* perform the corresponding operation on
// |SSL_PRIVATE_KEY_METHOD|. If there is a custom private key configured, they
@@ -1175,7 +1176,7 @@
// ssl_has_certificate returns one if a certificate and private key are
// configured and zero otherwise.
-int ssl_has_certificate(const SSL *ssl);
+int ssl_has_certificate(const SSL_CONFIG *cfg);
// ssl_parse_cert_chain parses a certificate list from |cbs| in the format used
// by a TLS Certificate message. On success, it advances |cbs| and returns
@@ -1194,10 +1195,10 @@
uint8_t *out_leaf_sha256, CBS *cbs,
CRYPTO_BUFFER_POOL *pool);
-// ssl_add_cert_chain adds |ssl|'s certificate chain to |cbb| in the format used
-// by a TLS Certificate message. If there is no certificate chain, it emits an
-// empty certificate list. It returns one on success and zero on error.
-int ssl_add_cert_chain(SSL *ssl, CBB *cbb);
+// ssl_add_cert_chain adds |hs->ssl|'s certificate chain to |cbb| in the format
+// used by a TLS Certificate message. If there is no certificate chain, it emits
+// an empty certificate list. It returns one on success and zero on error.
+int ssl_add_cert_chain(SSL_HANDSHAKE *hs, CBB *cbb);
// ssl_cert_check_digital_signature_key_usage parses the DER-encoded, X.509
// certificate in |in| and returns one if doesn't specify a key usage or, if it
@@ -1219,12 +1220,12 @@
CBS *cbs);
// ssl_has_client_CAs returns there are configured CAs.
-bool ssl_has_client_CAs(SSL *ssl);
+bool ssl_has_client_CAs(const SSL_CONFIG *cfg);
// ssl_add_client_CA_list adds the configured CA list to |cbb| in the format
// used by a TLS CertificateRequest message. It returns one on success and zero
// on error.
-int ssl_add_client_CA_list(SSL *ssl, CBB *cbb);
+int ssl_add_client_CA_list(SSL_HANDSHAKE *hs, CBB *cbb);
// ssl_check_leaf_certificate returns one if |pkey| and |leaf| are suitable as
// a server's leaf certificate for |hs|. Otherwise, it returns zero and pushes
@@ -1379,6 +1380,9 @@
// ssl is a non-owning pointer to the parent |SSL| object.
SSL *ssl;
+ // config is a non-owning pointer to the handshake configuration.
+ SSL_CONFIG *config;
+
// wait contains the operation the handshake is currently blocking on or
// |ssl_hs_ok| if none.
enum ssl_hs_wait_t wait = ssl_hs_ok;
@@ -1610,6 +1614,11 @@
// should be echoed in a ServerHello, or zero if no extension should be
// echoed.
uint16_t dummy_pq_padding_len = 0;
+
+ // handback indicates that a server should pause the handshake after
+ // finishing operations that require private key material, in such a way that
+ // |SSL_get_error| returns |SSL_HANDBACK|. It is set by |SSL_apply_handoff|.
+ bool handback : 1;
};
UniquePtr<SSL_HANDSHAKE> ssl_handshake_new(SSL *ssl);
@@ -1698,8 +1707,9 @@
enum ssl_cert_verify_context_t cert_verify_context);
// ssl_is_alpn_protocol_allowed returns whether |protocol| is a valid server
-// selection for |ssl|'s client preferences.
-bool ssl_is_alpn_protocol_allowed(const SSL *ssl, Span<const uint8_t> protocol);
+// selection for |hs->ssl|'s client preferences.
+bool ssl_is_alpn_protocol_allowed(const SSL_HANDSHAKE *hs,
+ Span<const uint8_t> protocol);
// ssl_negotiate_alpn negotiates the ALPN extension, if applicable. It returns
// true on successful negotiation or if nothing was negotiated. It returns false
@@ -1727,8 +1737,7 @@
enum ssl_hs_wait_t ssl_get_finished(SSL_HANDSHAKE *hs);
bool ssl_send_finished(SSL_HANDSHAKE *hs);
-bool ssl_output_cert_chain(SSL *ssl);
-
+bool ssl_output_cert_chain(SSL_HANDSHAKE *hs);
// SSLKEYLOGFILE functions.
@@ -1869,9 +1878,6 @@
// ticket key. Only sessions with a matching value will be accepted.
uint8_t sid_ctx_length = 0;
uint8_t sid_ctx[SSL_MAX_SID_CTX_LENGTH] = {0};
-
- // If enable_early_data is true, early data can be sent and accepted.
- bool enable_early_data:1;
};
// |SSL_PROTOCOL_METHOD| abstracts between TLS and DTLS.
@@ -2253,6 +2259,9 @@
// ClientHello and pause the handshake in such a way that |SSL_get_error|
// returns |SSL_HANDOFF|.
bool handoff:1;
+
+ // If enable_early_data is true, early data can be sent and accepted.
+ bool enable_early_data : 1;
};
// An ssl_shutdown_t describes the shutdown state of one end of the connection,
@@ -2580,147 +2589,90 @@
unsigned timeout_duration_ms = 0;
};
-// SSLConnection backs the public |SSL| type. Due to compatibility constraints,
-// it is a base class for |ssl_st|.
-struct SSLConnection {
- // method is the method table corresponding to the current protocol (DTLS or
- // TLS).
- const SSL_PROTOCOL_METHOD *method;
+// SSL_CONFIG contains configuration bits that can be shed after the handshake
+// completes. Objects of this type are not shared; they are unique to a
+// particular |SSL|.
+//
+// See SSL_shed_handshake_config() for more about the conditions under which
+// configuration can be shed.
+struct SSL_CONFIG {
+ explicit SSL_CONFIG(SSL *ssl_arg);
+ ~SSL_CONFIG();
- // version is the protocol version.
- uint16_t version;
+ // ssl is a non-owning pointer to the parent |SSL| object.
+ SSL *const ssl = nullptr;
// conf_max_version is the maximum acceptable protocol version configured by
// |SSL_set_max_proto_version|. Note this version is normalized in DTLS and is
// further constrainted by |SSL_OP_NO_*|.
- uint16_t conf_max_version;
+ uint16_t conf_max_version = 0;
// conf_min_version is the minimum acceptable protocol version configured by
// |SSL_set_min_proto_version|. Note this version is normalized in DTLS and is
// further constrainted by |SSL_OP_NO_*|.
- uint16_t conf_min_version;
+ uint16_t conf_min_version = 0;
- uint16_t max_send_fragment;
-
- // There are 2 BIO's even though they are normally both the same. This is so
- // data can be read and written to different handlers
-
- BIO *rbio; // used by SSL_read
- BIO *wbio; // used by SSL_write
-
- // do_handshake runs the handshake. On completion, it returns |ssl_hs_ok|.
- // Otherwise, it returns a value corresponding to what operation is needed to
- // progress.
- enum ssl_hs_wait_t (*do_handshake)(SSL_HANDSHAKE *hs);
-
- SSL3_STATE *s3; // SSLv3 variables
- DTLS1_STATE *d1; // DTLSv1 variables
-
- // callback that allows applications to peek at protocol messages
- void (*msg_callback)(int write_p, int version, int content_type,
- const void *buf, size_t len, SSL *ssl, void *arg);
- void *msg_callback_arg;
-
- X509_VERIFY_PARAM *param;
+ X509_VERIFY_PARAM *param = nullptr;
// crypto
- SSLCipherPreferenceList *cipher_list;
-
- // session info
+ SSLCipherPreferenceList *cipher_list = nullptr;
// This is used to hold the local certificate used (i.e. the server
// certificate for a server or the client certificate for a client).
- CERT *cert;
-
- // initial_timeout_duration_ms is the default DTLS timeout duration in
- // milliseconds. It's used to initialize the timer any time it's restarted.
- unsigned initial_timeout_duration_ms;
-
- // tls13_variant is the variant of TLS 1.3 we are using for this
- // configuration.
- enum tls13_variant_t tls13_variant;
-
- // session is the configured session to be offered by the client. This session
- // is immutable.
- SSL_SESSION *session;
+ CERT *cert = nullptr;
int (*verify_callback)(int ok,
- X509_STORE_CTX *ctx); // fail if callback returns 0
+ X509_STORE_CTX *ctx) =
+ nullptr; // fail if callback returns 0
- enum ssl_verify_result_t (*custom_verify_callback)(SSL *ssl,
- uint8_t *out_alert);
-
- void (*info_callback)(const SSL *ssl, int type, int value);
-
+ enum ssl_verify_result_t (*custom_verify_callback)(
+ SSL *ssl, uint8_t *out_alert) = nullptr;
// Server-only: psk_identity_hint is the identity hint to send in
// PSK-based key exchanges.
- char *psk_identity_hint;
+ char *psk_identity_hint = nullptr;
unsigned int (*psk_client_callback)(SSL *ssl, const char *hint,
char *identity,
unsigned int max_identity_len,
- uint8_t *psk, unsigned int max_psk_len);
+ uint8_t *psk,
+ unsigned int max_psk_len) = nullptr;
unsigned int (*psk_server_callback)(SSL *ssl, const char *identity,
- uint8_t *psk, unsigned int max_psk_len);
-
- SSL_CTX *ctx;
-
- // extra application data
- CRYPTO_EX_DATA ex_data;
+ uint8_t *psk,
+ unsigned int max_psk_len) = nullptr;
// for server side, keep the list of CA_dn we can use
- STACK_OF(CRYPTO_BUFFER) *client_CA;
+ STACK_OF(CRYPTO_BUFFER) *client_CA = nullptr;
// cached_x509_client_CA is a cache of parsed versions of the elements of
// |client_CA|.
- STACK_OF(X509_NAME) *cached_x509_client_CA;
+ STACK_OF(X509_NAME) *cached_x509_client_CA = nullptr;
- uint32_t options; // protocol behaviour
- uint32_t mode; // API behaviour
- uint32_t max_cert_list;
- uint16_t dummy_pq_padding_len;
- char *tlsext_hostname;
- size_t supported_group_list_len;
- uint16_t *supported_group_list; // our list
+ uint16_t dummy_pq_padding_len = 0;
+ size_t supported_group_list_len = 0;
+ uint16_t *supported_group_list = nullptr; // our list
// session_ctx is the |SSL_CTX| used for the session cache and related
// settings.
- SSL_CTX *session_ctx;
-
- // srtp_profiles is the list of configured SRTP protection profiles for
- // DTLS-SRTP.
- STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles;
+ SSL_CTX *session_ctx = nullptr;
// The client's Channel ID private key.
- EVP_PKEY *tlsext_channel_id_private;
+ EVP_PKEY *tlsext_channel_id_private = nullptr;
// For a client, this contains the list of supported protocols in wire
// format.
- uint8_t *alpn_client_proto_list;
- unsigned alpn_client_proto_list_len;
+ uint8_t *alpn_client_proto_list = nullptr;
+ unsigned alpn_client_proto_list_len = 0;
// Contains a list of supported Token Binding key parameters.
- uint8_t *token_binding_params;
- size_t token_binding_params_len;
+ uint8_t *token_binding_params = nullptr;
+ size_t token_binding_params_len = 0;
// Contains the QUIC transport params that this endpoint will send.
- uint8_t *quic_transport_params;
- size_t quic_transport_params_len;
-
- // renegotiate_mode controls how peer renegotiation attempts are handled.
- enum ssl_renegotiate_mode_t renegotiate_mode;
+ uint8_t *quic_transport_params = nullptr;
+ size_t quic_transport_params_len = 0;
// verify_mode is a bitmask of |SSL_VERIFY_*| values.
- uint8_t verify_mode;
-
- // server is true iff the this SSL* is the server half. Note: before the SSL*
- // is initialized by either SSL_set_accept_state or SSL_set_connect_state,
- // the side is not determined. In this state, server is always false.
- bool server:1;
-
- // quiet_shutdown is true if the connection should not send a close_notify on
- // shutdown.
- bool quiet_shutdown:1;
+ uint8_t verify_mode = SSL_VERIFY_NONE;
// Enable signed certificate time stamps. Currently client only.
bool signed_cert_timestamps_enabled:1;
@@ -2745,15 +2697,97 @@
// element of the same name and may be cleared if the handoff is declined.
bool handoff:1;
- // handback indicates that a server should pause the handshake after
- // finishing operations that require private key material, in such a way that
- // |SSL_get_error| returns |SSL_HANDBACK|. It is set by |SSL_apply_handoff|.
- bool handback : 1;
+ // shed_handshake_config indicates that the handshake config (this object!)
+ // should be freed after the handshake completes.
+ bool shed_handshake_config : 1;
+};
+
+// SSLConnection backs the public |SSL| type. Due to compatibility constraints,
+// it is a base class for |ssl_st|.
+struct SSLConnection {
+ // method is the method table corresponding to the current protocol (DTLS or
+ // TLS).
+ const SSL_PROTOCOL_METHOD *method;
+
+ // config is a container for handshake configuration. Accesses to this field
+ // should check for nullptr, since configuration may be shed after the
+ // handshake completes. (If you have the |SSL_HANDSHAKE| object at hand, use
+ // that instead, and skip the null check.)
+ SSL_CONFIG *config;
+
+ // version is the protocol version.
+ uint16_t version;
+
+ uint16_t max_send_fragment;
+
+ // There are 2 BIO's even though they are normally both the same. This is so
+ // data can be read and written to different handlers
+
+ BIO *rbio; // used by SSL_read
+ BIO *wbio; // used by SSL_write
+
+ // do_handshake runs the handshake. On completion, it returns |ssl_hs_ok|.
+ // Otherwise, it returns a value corresponding to what operation is needed to
+ // progress.
+ enum ssl_hs_wait_t (*do_handshake)(SSL_HANDSHAKE *hs);
+
+ SSL3_STATE *s3; // SSLv3 variables
+ DTLS1_STATE *d1; // DTLSv1 variables
+
+ // callback that allows applications to peek at protocol messages
+ void (*msg_callback)(int write_p, int version, int content_type,
+ const void *buf, size_t len, SSL *ssl, void *arg);
+ void *msg_callback_arg;
+
+ // session info
+
+ // initial_timeout_duration_ms is the default DTLS timeout duration in
+ // milliseconds. It's used to initialize the timer any time it's restarted.
+ unsigned initial_timeout_duration_ms;
+
+ // tls13_variant is the variant of TLS 1.3 we are using for this
+ // configuration.
+ enum tls13_variant_t tls13_variant;
+
+ // session is the configured session to be offered by the client. This session
+ // is immutable.
+ SSL_SESSION *session;
+
+ void (*info_callback)(const SSL *ssl, int type, int value);
+
+ SSL_CTX *ctx;
+
+ // extra application data
+ CRYPTO_EX_DATA ex_data;
+
+ uint32_t options; // protocol behaviour
+ uint32_t mode; // API behaviour
+ uint32_t max_cert_list;
+ char *tlsext_hostname;
+
+ // srtp_profiles is the list of configured SRTP protection profiles for
+ // DTLS-SRTP.
+ STACK_OF(SRTP_PROTECTION_PROFILE) * srtp_profiles;
+
+ // renegotiate_mode controls how peer renegotiation attempts are handled.
+ enum ssl_renegotiate_mode_t renegotiate_mode;
+
+ // server is true iff the this SSL* is the server half. Note: before the SSL*
+ // is initialized by either SSL_set_accept_state or SSL_set_connect_state,
+ // the side is not determined. In this state, server is always false.
+ bool server : 1;
+
+ // quiet_shutdown is true if the connection should not send a close_notify on
+ // shutdown.
+ bool quiet_shutdown : 1;
// did_dummy_pq_padding is only valid for a client. In that context, it is
// true iff the client observed the server echoing a dummy PQ padding
// extension.
bool did_dummy_pq_padding:1;
+
+ // If enable_early_data is true, early data can be sent and accepted.
+ bool enable_early_data : 1;
};
// From draft-ietf-tls-tls13-18, used in determining PSK modes.
@@ -2780,7 +2814,7 @@
const EVP_PKEY *privkey);
int ssl_cert_check_private_key(const CERT *cert, const EVP_PKEY *privkey);
int ssl_get_new_session(SSL_HANDSHAKE *hs, int is_server);
-int ssl_encrypt_ticket(SSL *ssl, CBB *out, const SSL_SESSION *session);
+int ssl_encrypt_ticket(SSL_HANDSHAKE *hs, CBB *out, const SSL_SESSION *session);
int ssl_ctx_rotate_ticket_encryption_key(SSL_CTX *ctx);
// ssl_session_new returns a newly-allocated blank |SSL_SESSION| or nullptr on
@@ -2799,8 +2833,9 @@
int ssl_session_serialize(const SSL_SESSION *in, CBB *cbb);
// ssl_session_is_context_valid returns one if |session|'s session ID context
-// matches the one set on |ssl| and zero otherwise.
-int ssl_session_is_context_valid(const SSL *ssl, const SSL_SESSION *session);
+// matches the one set on |hs| and zero otherwise.
+int ssl_session_is_context_valid(const SSL_HANDSHAKE *hs,
+ const SSL_SESSION *session);
// ssl_session_is_time_valid returns one if |session| is still valid and zero if
// it has expired.
@@ -2827,7 +2862,7 @@
// |ssl_hs_pending_session| and should be called again. If a ticket could not be
// decrypted immediately it returns |ssl_hs_pending_ticket| and should also
// be called again. Otherwise, it returns |ssl_hs_error|.
-enum ssl_hs_wait_t ssl_get_prev_session(SSL *ssl,
+enum ssl_hs_wait_t ssl_get_prev_session(SSL_HANDSHAKE *hs,
UniquePtr<SSL_SESSION> *out_session,
bool *out_tickets_supported,
bool *out_renew_ticket,
@@ -2856,10 +2891,6 @@
void ssl_session_renew_timeout(SSL *ssl, SSL_SESSION *session,
uint32_t timeout);
-// ssl_get_cipher_preferences returns the cipher preference list for TLS 1.2 and
-// below.
-const SSLCipherPreferenceList *ssl_get_cipher_preferences(const SSL *ssl);
-
void ssl_update_cache(SSL_HANDSHAKE *hs, int mode);
int ssl_send_alert(SSL *ssl, int level, int desc);
@@ -2952,11 +2983,11 @@
Span<const uint8_t> premaster);
// tls1_get_grouplist returns the locally-configured group preference list.
-Span<const uint16_t> tls1_get_grouplist(const SSL *ssl);
+Span<const uint16_t> tls1_get_grouplist(const SSL_HANDSHAKE *ssl);
// tls1_check_group_id returns one if |group_id| is consistent with
// locally-configured group preferences.
-int tls1_check_group_id(const SSL *ssl, uint16_t group_id);
+int tls1_check_group_id(const SSL_HANDSHAKE *ssl, uint16_t group_id);
// tls1_get_shared_group sets |*out_group_id| to the first preferred shared
// group between client and server preferences and returns one. If none may be
@@ -3000,9 +3031,9 @@
// Retry later.
// |ssl_ticket_aead_error|: an error occured that is fatal to the connection.
enum ssl_ticket_aead_result_t ssl_process_ticket(
- SSL *ssl, UniquePtr<SSL_SESSION> *out_session, bool *out_renew_ticket,
- const uint8_t *ticket, size_t ticket_len, const uint8_t *session_id,
- size_t session_id_len);
+ SSL_HANDSHAKE *hs, UniquePtr<SSL_SESSION> *out_session,
+ bool *out_renew_ticket, const uint8_t *ticket, size_t ticket_len,
+ const uint8_t *session_id, size_t session_id_len);
// tls1_verify_channel_id processes |msg| as a Channel ID message, and verifies
// the signature. If the key is valid, it saves the Channel ID and returns
@@ -3021,11 +3052,11 @@
int tls1_record_handshake_hashes_for_channel_id(SSL_HANDSHAKE *hs);
-// ssl_do_channel_id_callback checks runs |ssl->ctx->channel_id_cb| if
+// ssl_do_channel_id_callback checks runs |hs->ssl->ctx->channel_id_cb| if
// necessary. It returns one on success and zero on fatal error. Note that, on
-// success, |ssl->tlsext_channel_id_private| may be unset, in which case the
+// success, |hs->ssl->tlsext_channel_id_private| may be unset, in which case the
// operation should be retried later.
-int ssl_do_channel_id_callback(SSL *ssl);
+int ssl_do_channel_id_callback(SSL_HANDSHAKE *hs);
// ssl_can_write returns one if |ssl| is allowed to write and zero otherwise.
int ssl_can_write(const SSL *ssl);
@@ -3097,22 +3128,23 @@
// session_verify_cert_chain verifies the certificate chain in |session|,
// sets |session->verify_result| and returns one on success or zero on
// error.
- int (*session_verify_cert_chain)(SSL_SESSION *session, SSL *ssl,
+ int (*session_verify_cert_chain)(SSL_SESSION *session,
+ bssl::SSL_HANDSHAKE *ssl,
uint8_t *out_alert);
// hs_flush_cached_ca_names drops any cached |X509_NAME|s from |hs|.
void (*hs_flush_cached_ca_names)(bssl::SSL_HANDSHAKE *hs);
- // ssl_new does any neccessary initialisation of |ssl|. It returns one on
+ // ssl_new does any neccessary initialisation of |hs|. It returns one on
// success or zero on error.
- int (*ssl_new)(SSL *ssl);
+ int (*ssl_new)(bssl::SSL_HANDSHAKE *hs);
// ssl_free frees anything created by |ssl_new|.
- void (*ssl_free)(SSL *ssl);
+ void (*ssl_config_free)(bssl::SSL_CONFIG *cfg);
// ssl_flush_cached_client_CA drops any cached |X509_NAME|s from |ssl|.
- void (*ssl_flush_cached_client_CA)(SSL *ssl);
+ void (*ssl_flush_cached_client_CA)(bssl::SSL_CONFIG *cfg);
// ssl_auto_chain_if_needed runs the deprecated auto-chaining logic if
// necessary. On success, it updates |ssl|'s certificate configuration as
// needed and returns one. Otherwise, it returns zero.
- int (*ssl_auto_chain_if_needed)(SSL *ssl);
+ int (*ssl_auto_chain_if_needed)(bssl::SSL_HANDSHAKE *hs);
// ssl_ctx_new does any neccessary initialisation of |ctx|. It returns one on
// success or zero on error.
int (*ssl_ctx_new)(SSL_CTX *ctx);
diff --git a/ssl/s3_lib.cc b/ssl/s3_lib.cc
index b1fc5fb..d6a25b7 100644
--- a/ssl/s3_lib.cc
+++ b/ssl/s3_lib.cc
@@ -215,12 +215,4 @@
ssl->s3 = NULL;
}
-const SSLCipherPreferenceList *ssl_get_cipher_preferences(const SSL *ssl) {
- if (ssl->cipher_list != NULL) {
- return ssl->cipher_list;
- }
-
- return ssl->ctx->cipher_list;
-}
-
} // namespace bssl
diff --git a/ssl/ssl_cert.cc b/ssl/ssl_cert.cc
index 20b4514..730280c 100644
--- a/ssl/ssl_cert.cc
+++ b/ssl/ssl_cert.cc
@@ -136,7 +136,7 @@
namespace bssl {
CERT::CERT(const SSL_X509_METHOD *x509_method_arg)
- : x509_method(x509_method_arg), enable_early_data(false) {}
+ : x509_method(x509_method_arg) {}
CERT::~CERT() {
ssl_cert_clear_certs(this);
@@ -192,8 +192,6 @@
ret->sid_ctx_length = cert->sid_ctx_length;
OPENSSL_memcpy(ret->sid_ctx, cert->sid_ctx, sizeof(ret->sid_ctx));
- ret->enable_early_data = cert->enable_early_data;
-
return ret;
}
@@ -342,10 +340,10 @@
return 1;
}
-int ssl_has_certificate(const SSL *ssl) {
- return ssl->cert->chain != nullptr &&
- sk_CRYPTO_BUFFER_value(ssl->cert->chain.get(), 0) != nullptr &&
- ssl_has_private_key(ssl);
+int ssl_has_certificate(const SSL_CONFIG *cfg) {
+ return cfg->cert->chain != nullptr &&
+ sk_CRYPTO_BUFFER_value(cfg->cert->chain.get(), 0) != nullptr &&
+ ssl_has_private_key(cfg);
}
bool ssl_parse_cert_chain(uint8_t *out_alert,
@@ -412,8 +410,8 @@
return true;
}
-int ssl_add_cert_chain(SSL *ssl, CBB *cbb) {
- if (!ssl_has_certificate(ssl)) {
+int ssl_add_cert_chain(SSL_HANDSHAKE *hs, CBB *cbb) {
+ if (!ssl_has_certificate(hs->config)) {
return CBB_add_u24(cbb, 0);
}
@@ -423,7 +421,7 @@
return 0;
}
- STACK_OF(CRYPTO_BUFFER) *chain = ssl->cert->chain.get();
+ STACK_OF(CRYPTO_BUFFER) *chain = hs->config->cert->chain.get();
for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(chain); i++) {
CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(chain, i);
CBB child;
@@ -673,10 +671,10 @@
return ret;
}
-bool ssl_has_client_CAs(SSL *ssl) {
- STACK_OF(CRYPTO_BUFFER) *names = ssl->client_CA;
+bool ssl_has_client_CAs(const SSL_CONFIG *cfg) {
+ STACK_OF(CRYPTO_BUFFER) *names = cfg->client_CA;
if (names == NULL) {
- names = ssl->ctx->client_CA;
+ names = cfg->ssl->ctx->client_CA;
}
if (names == NULL) {
return false;
@@ -684,15 +682,15 @@
return sk_CRYPTO_BUFFER_num(names) > 0;
}
-int ssl_add_client_CA_list(SSL *ssl, CBB *cbb) {
+int ssl_add_client_CA_list(SSL_HANDSHAKE *hs, CBB *cbb) {
CBB child, name_cbb;
if (!CBB_add_u16_length_prefixed(cbb, &child)) {
return 0;
}
- STACK_OF(CRYPTO_BUFFER) *names = ssl->client_CA;
+ STACK_OF(CRYPTO_BUFFER) *names = hs->config->client_CA;
if (names == NULL) {
- names = ssl->ctx->client_CA;
+ names = hs->ssl->ctx->client_CA;
}
if (names == NULL) {
return CBB_flush(cbb);
@@ -711,8 +709,7 @@
int ssl_check_leaf_certificate(SSL_HANDSHAKE *hs, EVP_PKEY *pkey,
const CRYPTO_BUFFER *leaf) {
- SSL *const ssl = hs->ssl;
- assert(ssl_protocol_version(ssl) < TLS1_3_VERSION);
+ assert(ssl_protocol_version(hs->ssl) < TLS1_3_VERSION);
// Check the certificate's type matches the cipher.
if (!(hs->new_cipher->algorithm_auth & ssl_cipher_auth_mask_for_key(pkey))) {
@@ -740,7 +737,7 @@
uint16_t group_id;
if (!ssl_nid_to_group_id(
&group_id, EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key))) ||
- !tls1_check_group_id(ssl, group_id) ||
+ !tls1_check_group_id(hs, group_id) ||
EC_KEY_get_conv_form(ec_key) != POINT_CONVERSION_UNCOMPRESSED) {
OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECC_CERT);
return 0;
@@ -752,18 +749,18 @@
int ssl_on_certificate_selected(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- if (!ssl_has_certificate(ssl)) {
+ if (!ssl_has_certificate(hs->config)) {
// Nothing to do.
return 1;
}
- if (!ssl->ctx->x509_method->ssl_auto_chain_if_needed(ssl)) {
+ if (!ssl->ctx->x509_method->ssl_auto_chain_if_needed(hs)) {
return 0;
}
CBS leaf;
- CRYPTO_BUFFER_init_CBS(sk_CRYPTO_BUFFER_value(ssl->cert->chain.get(), 0),
- &leaf);
+ CRYPTO_BUFFER_init_CBS(
+ sk_CRYPTO_BUFFER_value(hs->config->cert->chain.get(), 0), &leaf);
hs->local_pubkey = ssl_cert_parse_pubkey(&leaf);
return hs->local_pubkey != NULL;
@@ -776,7 +773,10 @@
int SSL_set_chain_and_key(SSL *ssl, CRYPTO_BUFFER *const *certs,
size_t num_certs, EVP_PKEY *privkey,
const SSL_PRIVATE_KEY_METHOD *privkey_method) {
- return cert_set_chain_and_key(ssl->cert, certs, num_certs, privkey,
+ if (!ssl->config) {
+ return 0;
+ }
+ return cert_set_chain_and_key(ssl->config->cert, certs, num_certs, privkey,
privkey_method);
}
@@ -799,11 +799,11 @@
int SSL_use_certificate_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) {
UniquePtr<CRYPTO_BUFFER> buffer(CRYPTO_BUFFER_new(der, der_len, NULL));
- if (!buffer) {
+ if (!buffer || !ssl->config) {
return 0;
}
- return ssl_set_cert(ssl->cert, std::move(buffer));
+ return ssl_set_cert(ssl->config->cert, std::move(buffer));
}
void SSL_CTX_set_cert_cb(SSL_CTX *ctx, int (*cb)(SSL *ssl, void *arg),
@@ -812,7 +812,10 @@
}
void SSL_set_cert_cb(SSL *ssl, int (*cb)(SSL *ssl, void *arg), void *arg) {
- ssl_cert_set_cert_cb(ssl->cert, cb, arg);
+ if (!ssl->config) {
+ return;
+ }
+ ssl_cert_set_cert_cb(ssl->config->cert, cb, arg);
}
STACK_OF(CRYPTO_BUFFER) *SSL_get0_peer_certificates(const SSL *ssl) {
@@ -852,7 +855,10 @@
int SSL_set_signed_cert_timestamp_list(SSL *ssl, const uint8_t *list,
size_t list_len) {
- return set_signed_cert_timestamp_list(ssl->cert, list, list_len);
+ if (!ssl->config) {
+ return 0;
+ }
+ return set_signed_cert_timestamp_list(ssl->config->cert, list, list_len);
}
int SSL_CTX_set_ocsp_response(SSL_CTX *ctx, const uint8_t *response,
@@ -864,9 +870,12 @@
int SSL_set_ocsp_response(SSL *ssl, const uint8_t *response,
size_t response_len) {
- ssl->cert->ocsp_response.reset(
+ if (!ssl->config) {
+ return 0;
+ }
+ ssl->config->cert->ocsp_response.reset(
CRYPTO_BUFFER_new(response, response_len, nullptr));
- return ssl->cert->ocsp_response != nullptr;
+ return ssl->config->cert->ocsp_response != nullptr;
}
void SSL_CTX_set0_client_CAs(SSL_CTX *ctx, STACK_OF(CRYPTO_BUFFER) *name_list) {
@@ -876,7 +885,10 @@
}
void SSL_set0_client_CAs(SSL *ssl, STACK_OF(CRYPTO_BUFFER) *name_list) {
- ssl->ctx->x509_method->ssl_flush_cached_client_CA(ssl);
- sk_CRYPTO_BUFFER_pop_free(ssl->client_CA, CRYPTO_BUFFER_free);
- ssl->client_CA = name_list;
+ if (!ssl->config) {
+ return;
+ }
+ ssl->ctx->x509_method->ssl_flush_cached_client_CA(ssl->config);
+ sk_CRYPTO_BUFFER_pop_free(ssl->config->client_CA, CRYPTO_BUFFER_free);
+ ssl->config->client_CA = name_list;
}
diff --git a/ssl/ssl_lib.cc b/ssl/ssl_lib.cc
index 78a1860..1e5b3d1 100644
--- a/ssl/ssl_lib.cc
+++ b/ssl/ssl_lib.cc
@@ -274,7 +274,7 @@
void ssl_update_cache(SSL_HANDSHAKE *hs, int mode) {
SSL *const ssl = hs->ssl;
- SSL_CTX *ctx = ssl->session_ctx;
+ SSL_CTX *ctx = hs->config->session_ctx;
// Never cache sessions with empty session IDs.
if (ssl->s3->established_session->session_id_length == 0 ||
ssl->s3->established_session->not_resumable ||
@@ -648,8 +648,12 @@
}
OPENSSL_memset(ssl, 0, sizeof(SSL));
- ssl->conf_min_version = ctx->conf_min_version;
- ssl->conf_max_version = ctx->conf_max_version;
+ ssl->config = New<SSL_CONFIG>(ssl);
+ if (ssl->config == nullptr) {
+ goto err;
+ }
+ ssl->config->conf_min_version = ctx->conf_min_version;
+ ssl->config->conf_max_version = ctx->conf_max_version;
ssl->tls13_variant = ctx->tls13_variant;
// RFC 6347 states that implementations SHOULD use an initial timer value of
@@ -660,47 +664,44 @@
ssl->mode = ctx->mode;
ssl->max_cert_list = ctx->max_cert_list;
- ssl->cert = ssl_cert_dup(ctx->cert).release();
- if (ssl->cert == NULL) {
+ ssl->config->cert = ssl_cert_dup(ctx->cert).release();
+ if (ssl->config->cert == NULL) {
goto err;
}
ssl->msg_callback = ctx->msg_callback;
ssl->msg_callback_arg = ctx->msg_callback_arg;
- ssl->verify_mode = ctx->verify_mode;
- ssl->verify_callback = ctx->default_verify_callback;
- ssl->custom_verify_callback = ctx->custom_verify_callback;
- ssl->retain_only_sha256_of_client_certs =
+ ssl->config->verify_mode = ctx->verify_mode;
+ ssl->config->verify_callback = ctx->default_verify_callback;
+ ssl->config->custom_verify_callback = ctx->custom_verify_callback;
+ ssl->config->retain_only_sha256_of_client_certs =
ctx->retain_only_sha256_of_client_certs;
ssl->quiet_shutdown = ctx->quiet_shutdown;
ssl->max_send_fragment = ctx->max_send_fragment;
+ ssl->enable_early_data = ctx->enable_early_data;
SSL_CTX_up_ref(ctx);
ssl->ctx = ctx;
SSL_CTX_up_ref(ctx);
- ssl->session_ctx = ctx;
-
- if (!ssl->ctx->x509_method->ssl_new(ssl)) {
- goto err;
- }
+ ssl->config->session_ctx = ctx;
if (ctx->supported_group_list) {
- ssl->supported_group_list = (uint16_t *)BUF_memdup(
+ ssl->config->supported_group_list = (uint16_t *)BUF_memdup(
ctx->supported_group_list, ctx->supported_group_list_len * 2);
- if (!ssl->supported_group_list) {
+ if (!ssl->config->supported_group_list) {
goto err;
}
- ssl->supported_group_list_len = ctx->supported_group_list_len;
+ ssl->config->supported_group_list_len = ctx->supported_group_list_len;
}
if (ctx->alpn_client_proto_list) {
- ssl->alpn_client_proto_list = (uint8_t *)BUF_memdup(
+ ssl->config->alpn_client_proto_list = (uint8_t *)BUF_memdup(
ctx->alpn_client_proto_list, ctx->alpn_client_proto_list_len);
- if (ssl->alpn_client_proto_list == NULL) {
+ if (ssl->config->alpn_client_proto_list == NULL) {
goto err;
}
- ssl->alpn_client_proto_list_len = ctx->alpn_client_proto_list_len;
+ ssl->config->alpn_client_proto_list_len = ctx->alpn_client_proto_list_len;
}
ssl->method = ctx->method;
@@ -709,27 +710,31 @@
goto err;
}
+ if (!ssl->ctx->x509_method->ssl_new(ssl->s3->hs.get())) {
+ goto err;
+ }
+
CRYPTO_new_ex_data(&ssl->ex_data);
- ssl->psk_identity_hint = NULL;
if (ctx->psk_identity_hint) {
- ssl->psk_identity_hint = BUF_strdup(ctx->psk_identity_hint);
- if (ssl->psk_identity_hint == NULL) {
+ ssl->config->psk_identity_hint = BUF_strdup(ctx->psk_identity_hint);
+ if (ssl->config->psk_identity_hint == NULL) {
goto err;
}
}
- ssl->psk_client_callback = ctx->psk_client_callback;
- ssl->psk_server_callback = ctx->psk_server_callback;
+ ssl->config->psk_client_callback = ctx->psk_client_callback;
+ ssl->config->psk_server_callback = ctx->psk_server_callback;
- ssl->tlsext_channel_id_enabled = ctx->tlsext_channel_id_enabled;
+ ssl->config->tlsext_channel_id_enabled = ctx->tlsext_channel_id_enabled;
if (ctx->tlsext_channel_id_private) {
EVP_PKEY_up_ref(ctx->tlsext_channel_id_private);
- ssl->tlsext_channel_id_private = ctx->tlsext_channel_id_private;
+ ssl->config->tlsext_channel_id_private = ctx->tlsext_channel_id_private;
}
- ssl->signed_cert_timestamps_enabled = ctx->signed_cert_timestamps_enabled;
- ssl->ocsp_stapling_enabled = ctx->ocsp_stapling_enabled;
- ssl->handoff = ctx->handoff;
+ ssl->config->signed_cert_timestamps_enabled =
+ ctx->signed_cert_timestamps_enabled;
+ ssl->config->ocsp_stapling_enabled = ctx->ocsp_stapling_enabled;
+ ssl->config->handoff = ctx->handoff;
return ssl;
@@ -740,36 +745,49 @@
return NULL;
}
+SSL_CONFIG::SSL_CONFIG(SSL *ssl_arg)
+ : ssl(ssl_arg),
+ signed_cert_timestamps_enabled(false),
+ ocsp_stapling_enabled(false),
+ tlsext_channel_id_enabled(false),
+ retain_only_sha256_of_client_certs(false),
+ handoff(false),
+ shed_handshake_config(false) {
+ assert(ssl);
+}
+
+SSL_CONFIG::~SSL_CONFIG() {
+ if (ssl->ctx != nullptr) {
+ ssl->ctx->x509_method->ssl_config_free(this);
+ }
+ Delete(cipher_list);
+ Delete(cert);
+ SSL_CTX_free(session_ctx);
+ OPENSSL_free(supported_group_list);
+ OPENSSL_free(alpn_client_proto_list);
+ OPENSSL_free(token_binding_params);
+ OPENSSL_free(quic_transport_params);
+ EVP_PKEY_free(tlsext_channel_id_private);
+ OPENSSL_free(psk_identity_hint);
+ sk_CRYPTO_BUFFER_pop_free(client_CA, CRYPTO_BUFFER_free);
+}
+
void SSL_free(SSL *ssl) {
if (ssl == NULL) {
return;
}
- if (ssl->ctx != NULL) {
- ssl->ctx->x509_method->ssl_free(ssl);
- }
-
CRYPTO_free_ex_data(&g_ex_data_class_ssl, ssl, &ssl->ex_data);
BIO_free_all(ssl->rbio);
BIO_free_all(ssl->wbio);
- // add extra stuff
- Delete(ssl->cipher_list);
+ Delete(ssl->config);
+ ssl->config = NULL;
SSL_SESSION_free(ssl->session);
- Delete(ssl->cert);
-
OPENSSL_free(ssl->tlsext_hostname);
- SSL_CTX_free(ssl->session_ctx);
- OPENSSL_free(ssl->supported_group_list);
- OPENSSL_free(ssl->alpn_client_proto_list);
- OPENSSL_free(ssl->token_binding_params);
- OPENSSL_free(ssl->quic_transport_params);
- EVP_PKEY_free(ssl->tlsext_channel_id_private);
- OPENSSL_free(ssl->psk_identity_hint);
- sk_CRYPTO_BUFFER_pop_free(ssl->client_CA, CRYPTO_BUFFER_free);
sk_SRTP_PROTECTION_PROFILE_free(ssl->srtp_profiles);
if (ssl->method != NULL) {
@@ -863,6 +881,12 @@
// Destroy the handshake object if the handshake has completely finished.
if (!early_return) {
+ if (hs->config->shed_handshake_config) {
+ assert(ssl->config == hs->config);
+ Delete(ssl->config);
+ ssl->config = nullptr;
+ hs->config = nullptr;
+ }
ssl->s3->hs.reset();
}
@@ -923,6 +947,11 @@
break;
}
+ // Reject renegotiation when the handshake config has been shed.
+ if (!ssl->config) {
+ goto no_renegotiation;
+ }
+
// Renegotiation is only supported at quiescent points in the application
// protocol, namely in HTTPS, just before reading the HTTP response. Require
// the record-layer be idle and avoid complexities of sending a handshake
@@ -1161,11 +1190,15 @@
int SSL_set_quic_transport_params(SSL *ssl, const uint8_t *params,
size_t params_len) {
- ssl->quic_transport_params = (uint8_t *)BUF_memdup(params, params_len);
- if (!ssl->quic_transport_params) {
+ if (!ssl->config) {
return 0;
}
- ssl->quic_transport_params_len = params_len;
+ ssl->config->quic_transport_params =
+ (uint8_t *)BUF_memdup(params, params_len);
+ if (!ssl->config->quic_transport_params) {
+ return 0;
+ }
+ ssl->config->quic_transport_params_len = params_len;
return 1;
}
@@ -1177,7 +1210,7 @@
}
void SSL_CTX_set_early_data_enabled(SSL_CTX *ctx, int enabled) {
- ctx->cert->enable_early_data = !!enabled;
+ ctx->enable_early_data = !!enabled;
}
void SSL_CTX_set_tls13_variant(SSL_CTX *ctx, enum tls13_variant_t variant) {
@@ -1189,7 +1222,7 @@
}
void SSL_set_early_data_enabled(SSL *ssl, int enabled) {
- ssl->cert->enable_early_data = !!enabled;
+ ssl->enable_early_data = !!enabled;
}
int SSL_in_early_data(const SSL *ssl) {
@@ -1436,15 +1469,28 @@
int SSL_set_session_id_context(SSL *ssl, const uint8_t *sid_ctx,
size_t sid_ctx_len) {
- return set_session_id_context(ssl->cert, sid_ctx, sid_ctx_len);
+ if (!ssl->config) {
+ return 0;
+ }
+ return set_session_id_context(ssl->config->cert, sid_ctx, sid_ctx_len);
}
const uint8_t *SSL_get0_session_id_context(const SSL *ssl, size_t *out_len) {
- *out_len = ssl->cert->sid_ctx_length;
- return ssl->cert->sid_ctx;
+ if (!ssl->config) {
+ assert(ssl->config);
+ *out_len = 0;
+ return NULL;
+ }
+ *out_len = ssl->config->cert->sid_ctx_length;
+ return ssl->config->cert->sid_ctx;
}
-void SSL_certs_clear(SSL *ssl) { ssl_cert_clear_certs(ssl->cert); }
+void SSL_certs_clear(SSL *ssl) {
+ if (!ssl->config) {
+ return;
+ }
+ ssl_cert_clear_certs(ssl->config->cert);
+}
int SSL_get_fd(const SSL *ssl) { return SSL_get_rfd(ssl); }
@@ -1557,7 +1603,13 @@
ssl->s3->previous_server_finished_len);
}
-int SSL_get_verify_mode(const SSL *ssl) { return ssl->verify_mode; }
+int SSL_get_verify_mode(const SSL *ssl) {
+ if (!ssl->config) {
+ assert(ssl->config);
+ return -1;
+ }
+ return ssl->config->verify_mode;
+}
int SSL_get_extms_support(const SSL *ssl) {
// TLS 1.3 does not require extended master secret and always reports as
@@ -1601,7 +1653,11 @@
// Fix this function so that it takes an optional type parameter
int SSL_check_private_key(const SSL *ssl) {
- return ssl_cert_check_private_key(ssl->cert, ssl->cert->privatekey.get());
+ if (!ssl->config) {
+ return 0;
+ }
+ return ssl_cert_check_private_key(ssl->config->cert,
+ ssl->config->cert->privatekey.get());
}
long SSL_get_default_timeout(const SSL *ssl) {
@@ -1775,8 +1831,11 @@
}
int SSL_set1_curves(SSL *ssl, const int *curves, size_t curves_len) {
- return tls1_set_curves(&ssl->supported_group_list,
- &ssl->supported_group_list_len, curves,
+ if (!ssl->config) {
+ return 0;
+ }
+ return tls1_set_curves(&ssl->config->supported_group_list,
+ &ssl->config->supported_group_list_len, curves,
curves_len);
}
@@ -1786,8 +1845,11 @@
}
int SSL_set1_curves_list(SSL *ssl, const char *curves) {
- return tls1_set_curves_list(&ssl->supported_group_list,
- &ssl->supported_group_list_len, curves);
+ if (!ssl->config) {
+ return 0;
+ }
+ return tls1_set_curves_list(&ssl->config->supported_group_list,
+ &ssl->config->supported_group_list_len, curves);
}
uint16_t SSL_get_curve_id(const SSL *ssl) {
@@ -1824,9 +1886,13 @@
if (ssl == NULL) {
return NULL;
}
+ if (ssl->config == NULL) {
+ assert(ssl->config);
+ return NULL;
+ }
- const SSLCipherPreferenceList *prefs = ssl_get_cipher_preferences(ssl);
- return prefs == nullptr ? nullptr : prefs->ciphers.get();
+ return ssl->config->cipher_list ? ssl->config->cipher_list->ciphers.get()
+ : ssl->ctx->cipher_list->ciphers.get();
}
const char *SSL_get_cipher_list(const SSL *ssl, int n) {
@@ -1856,11 +1922,19 @@
}
int SSL_set_cipher_list(SSL *ssl, const char *str) {
- return ssl_create_cipher_list(&ssl->cipher_list, str, false /* not strict */);
+ if (!ssl->config) {
+ return 0;
+ }
+ return ssl_create_cipher_list(&ssl->config->cipher_list, str,
+ false /* not strict */);
}
int SSL_set_strict_cipher_list(SSL *ssl, const char *str) {
- return ssl_create_cipher_list(&ssl->cipher_list, str, true /* strict */);
+ if (!ssl->config) {
+ return 0;
+ }
+ return ssl_create_cipher_list(&ssl->config->cipher_list, str,
+ true /* strict */);
}
const char *SSL_get_servername(const SSL *ssl, const int type) {
@@ -1894,8 +1968,11 @@
void SSL_set_custom_verify(
SSL *ssl, int mode,
enum ssl_verify_result_t (*callback)(SSL *ssl, uint8_t *out_alert)) {
- ssl->verify_mode = mode;
- ssl->custom_verify_callback = callback;
+ if (!ssl->config) {
+ return;
+ }
+ ssl->config->verify_mode = mode;
+ ssl->config->custom_verify_callback = callback;
}
void SSL_CTX_enable_signed_cert_timestamps(SSL_CTX *ctx) {
@@ -1903,7 +1980,10 @@
}
void SSL_enable_signed_cert_timestamps(SSL *ssl) {
- ssl->signed_cert_timestamps_enabled = true;
+ if (!ssl->config) {
+ return;
+ }
+ ssl->config->signed_cert_timestamps_enabled = true;
}
void SSL_CTX_enable_ocsp_stapling(SSL_CTX *ctx) {
@@ -1911,7 +1991,10 @@
}
void SSL_enable_ocsp_stapling(SSL *ssl) {
- ssl->ocsp_stapling_enabled = true;
+ if (!ssl->config) {
+ return;
+ }
+ ssl->config->ocsp_stapling_enabled = true;
}
void SSL_get0_signed_cert_timestamp_list(const SSL *ssl, const uint8_t **out,
@@ -2040,12 +2123,16 @@
}
int SSL_set_alpn_protos(SSL *ssl, const uint8_t *protos, unsigned protos_len) {
- OPENSSL_free(ssl->alpn_client_proto_list);
- ssl->alpn_client_proto_list = (uint8_t *)BUF_memdup(protos, protos_len);
- if (!ssl->alpn_client_proto_list) {
+ if (!ssl->config) {
+ return 0;
+ }
+ OPENSSL_free(ssl->config->alpn_client_proto_list);
+ ssl->config->alpn_client_proto_list =
+ (uint8_t *)BUF_memdup(protos, protos_len);
+ if (!ssl->config->alpn_client_proto_list) {
return 1;
}
- ssl->alpn_client_proto_list_len = protos_len;
+ ssl->config->alpn_client_proto_list_len = protos_len;
return 0;
}
@@ -2084,7 +2171,10 @@
}
void SSL_set_tls_channel_id_enabled(SSL *ssl, int enabled) {
- ssl->tlsext_channel_id_enabled = !!enabled;
+ if (!ssl->config) {
+ return;
+ }
+ ssl->config->tlsext_channel_id_enabled = !!enabled;
}
int SSL_enable_tls_channel_id(SSL *ssl) {
@@ -2114,15 +2204,18 @@
}
int SSL_set1_tls_channel_id(SSL *ssl, EVP_PKEY *private_key) {
+ if (!ssl->config) {
+ return 0;
+ }
if (!is_p256_key(private_key)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_NOT_P256);
return 0;
}
- EVP_PKEY_free(ssl->tlsext_channel_id_private);
+ EVP_PKEY_free(ssl->config->tlsext_channel_id_private);
EVP_PKEY_up_ref(private_key);
- ssl->tlsext_channel_id_private = private_key;
- ssl->tlsext_channel_id_enabled = true;
+ ssl->config->tlsext_channel_id_private = private_key;
+ ssl->config->tlsext_channel_id_enabled = true;
return 1;
}
@@ -2137,16 +2230,19 @@
}
int SSL_set_token_binding_params(SSL *ssl, const uint8_t *params, size_t len) {
+ if (!ssl->config) {
+ return 0;
+ }
if (len > 256) {
OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
return 0;
}
- OPENSSL_free(ssl->token_binding_params);
- ssl->token_binding_params = (uint8_t *)BUF_memdup(params, len);
- if (!ssl->token_binding_params) {
+ OPENSSL_free(ssl->config->token_binding_params);
+ ssl->config->token_binding_params = (uint8_t *)BUF_memdup(params, len);
+ if (!ssl->config->token_binding_params) {
return 0;
}
- ssl->token_binding_params_len = len;
+ ssl->config->token_binding_params_len = len;
return 1;
}
@@ -2168,8 +2264,12 @@
}
EVP_PKEY *SSL_get_privatekey(const SSL *ssl) {
- if (ssl->cert != NULL) {
- return ssl->cert->privatekey.get();
+ if (!ssl->config) {
+ assert(ssl->config);
+ return NULL;
+ }
+ if (ssl->config->cert != NULL) {
+ return ssl->config->cert->privatekey.get();
}
return NULL;
@@ -2244,6 +2344,9 @@
SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl) { return ssl->ctx; }
SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx) {
+ if (!ssl->config) {
+ return NULL;
+ }
if (ssl->ctx == ctx) {
return ssl->ctx;
}
@@ -2255,15 +2358,16 @@
}
if (ctx == NULL) {
- ctx = ssl->session_ctx;
+ ctx = ssl->config->session_ctx;
}
- Delete(ssl->cert);
- ssl->cert = ssl_cert_dup(ctx->cert).release();
+ Delete(ssl->config->cert);
+ ssl->config->cert = ssl_cert_dup(ctx->cert).release();
SSL_CTX_up_ref(ctx);
SSL_CTX_free(ssl->ctx);
ssl->ctx = ctx;
+ ssl->enable_early_data = ssl->ctx->enable_early_data;
return ssl->ctx;
}
@@ -2374,14 +2478,21 @@
}
int SSL_use_psk_identity_hint(SSL *ssl, const char *identity_hint) {
- return use_psk_identity_hint(&ssl->psk_identity_hint, identity_hint);
+ if (!ssl->config) {
+ return 0;
+ }
+ return use_psk_identity_hint(&ssl->config->psk_identity_hint, identity_hint);
}
const char *SSL_get_psk_identity_hint(const SSL *ssl) {
if (ssl == NULL) {
return NULL;
}
- return ssl->psk_identity_hint;
+ if (ssl->config == NULL) {
+ assert(ssl->config);
+ return NULL;
+ }
+ return ssl->config->psk_identity_hint;
}
const char *SSL_get_psk_identity(const SSL *ssl) {
@@ -2399,7 +2510,10 @@
SSL *ssl, unsigned (*cb)(SSL *ssl, const char *hint, char *identity,
unsigned max_identity_len, uint8_t *psk,
unsigned max_psk_len)) {
- ssl->psk_client_callback = cb;
+ if (!ssl->config) {
+ return;
+ }
+ ssl->config->psk_client_callback = cb;
}
void SSL_CTX_set_psk_client_callback(
@@ -2412,7 +2526,10 @@
void SSL_set_psk_server_callback(
SSL *ssl, unsigned (*cb)(SSL *ssl, const char *identity, uint8_t *psk,
unsigned max_psk_len)) {
- ssl->psk_server_callback = cb;
+ if (!ssl->config) {
+ return;
+ }
+ ssl->config->psk_server_callback = cb;
}
void SSL_CTX_set_psk_server_callback(
@@ -2422,11 +2539,14 @@
}
int SSL_set_dummy_pq_padding_size(SSL *ssl, size_t num_bytes) {
+ if (!ssl->config) {
+ return 0;
+ }
if (num_bytes > 0xffff) {
return 0;
}
- ssl->dummy_pq_padding_len = num_bytes;
+ ssl->config->dummy_pq_padding_len = num_bytes;
return 1;
}
@@ -2605,7 +2725,10 @@
}
void SSL_set_retain_only_sha256_of_client_certs(SSL *ssl, int enabled) {
- ssl->retain_only_sha256_of_client_certs = !!enabled;
+ if (!ssl->config) {
+ return;
+ }
+ ssl->config->retain_only_sha256_of_client_certs = !!enabled;
}
void SSL_CTX_set_retain_only_sha256_of_client_certs(SSL_CTX *ctx, int enabled) {
@@ -2626,7 +2749,18 @@
int SSL_is_draft_downgrade(const SSL *ssl) { return ssl->s3->draft_downgrade; }
+void SSL_set_shed_handshake_config(SSL *ssl, int enable) {
+ if (!ssl->config) {
+ return;
+ }
+ ssl->config->shed_handshake_config = !!enable;
+}
+
int SSL_clear(SSL *ssl) {
+ if (!ssl->config) {
+ return 0; // SSL_clear may not be used after shedding config.
+ }
+
// In OpenSSL, reusing a client |SSL| with |SSL_clear| causes the previously
// established session to be offered the next time around. wpa_supplicant
// depends on this behavior, so emulate it.
diff --git a/ssl/ssl_privkey.cc b/ssl/ssl_privkey.cc
index bba03b7..0fcd805 100644
--- a/ssl/ssl_privkey.cc
+++ b/ssl/ssl_privkey.cc
@@ -134,8 +134,8 @@
return NULL;
}
-int ssl_has_private_key(const SSL *ssl) {
- return ssl->cert->privatekey != nullptr || ssl->cert->key_method != nullptr;
+int ssl_has_private_key(const SSL_CONFIG *cfg) {
+ return cfg->cert->privatekey != nullptr || cfg->cert->key_method != nullptr;
}
static int pkey_supports_algorithm(const SSL *ssl, EVP_PKEY *pkey,
@@ -196,13 +196,13 @@
SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len, size_t max_out,
uint16_t sigalg, Span<const uint8_t> in) {
SSL *const ssl = hs->ssl;
- if (ssl->cert->key_method != NULL) {
+ if (hs->config->cert->key_method != NULL) {
enum ssl_private_key_result_t ret;
if (hs->pending_private_key_op) {
- ret = ssl->cert->key_method->complete(ssl, out, out_len, max_out);
+ ret = hs->config->cert->key_method->complete(ssl, out, out_len, max_out);
} else {
- ret = ssl->cert->key_method->sign(ssl, out, out_len, max_out, sigalg,
- in.data(), in.size());
+ ret = hs->config->cert->key_method->sign(ssl, out, out_len, max_out,
+ sigalg, in.data(), in.size());
}
if (ret == ssl_private_key_failure) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PRIVATE_KEY_OPERATION_FAILED);
@@ -213,7 +213,7 @@
*out_len = max_out;
ScopedEVP_MD_CTX ctx;
- if (!setup_ctx(ssl, ctx.get(), ssl->cert->privatekey.get(), sigalg,
+ if (!setup_ctx(ssl, ctx.get(), hs->config->cert->privatekey.get(), sigalg,
0 /* sign */) ||
!EVP_DigestSign(ctx.get(), out, out_len, in.data(), in.size())) {
return ssl_private_key_failure;
@@ -236,13 +236,13 @@
size_t max_out,
Span<const uint8_t> in) {
SSL *const ssl = hs->ssl;
- if (ssl->cert->key_method != NULL) {
+ if (hs->config->cert->key_method != NULL) {
enum ssl_private_key_result_t ret;
if (hs->pending_private_key_op) {
- ret = ssl->cert->key_method->complete(ssl, out, out_len, max_out);
+ ret = hs->config->cert->key_method->complete(ssl, out, out_len, max_out);
} else {
- ret = ssl->cert->key_method->decrypt(ssl, out, out_len, max_out,
- in.data(), in.size());
+ ret = hs->config->cert->key_method->decrypt(ssl, out, out_len, max_out,
+ in.data(), in.size());
}
if (ret == ssl_private_key_failure) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PRIVATE_KEY_OPERATION_FAILED);
@@ -251,7 +251,7 @@
return ret;
}
- RSA *rsa = EVP_PKEY_get0_RSA(ssl->cert->privatekey.get());
+ RSA *rsa = EVP_PKEY_get0_RSA(hs->config->cert->privatekey.get());
if (rsa == NULL) {
// Decrypt operations are only supported for RSA keys.
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
@@ -294,7 +294,7 @@
using namespace bssl;
int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) {
- if (rsa == NULL) {
+ if (rsa == NULL || ssl->config == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
@@ -306,7 +306,7 @@
return 0;
}
- return ssl_set_pkey(ssl->cert, pkey.get());
+ return ssl_set_pkey(ssl->config->cert, pkey.get());
}
int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) {
@@ -320,12 +320,12 @@
}
int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) {
- if (pkey == NULL) {
+ if (pkey == NULL || ssl->config == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
- return ssl_set_pkey(ssl->cert, pkey);
+ return ssl_set_pkey(ssl->config->cert, pkey);
}
int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const uint8_t *der,
@@ -400,7 +400,10 @@
void SSL_set_private_key_method(SSL *ssl,
const SSL_PRIVATE_KEY_METHOD *key_method) {
- ssl->cert->key_method = key_method;
+ if (!ssl->config) {
+ return;
+ }
+ ssl->config->cert->key_method = key_method;
}
void SSL_CTX_set_private_key_method(SSL_CTX *ctx,
@@ -482,7 +485,10 @@
int SSL_set_signing_algorithm_prefs(SSL *ssl, const uint16_t *prefs,
size_t num_prefs) {
- return ssl->cert->sigalgs.CopyFrom(MakeConstSpan(prefs, num_prefs));
+ if (!ssl->config) {
+ return 0;
+ }
+ return ssl->config->cert->sigalgs.CopyFrom(MakeConstSpan(prefs, num_prefs));
}
int SSL_CTX_set_verify_algorithm_prefs(SSL_CTX *ctx, const uint16_t *prefs,
diff --git a/ssl/ssl_session.cc b/ssl/ssl_session.cc
index 272fc55..b992e9a 100644
--- a/ssl/ssl_session.cc
+++ b/ssl/ssl_session.cc
@@ -381,13 +381,13 @@
if (version >= TLS1_3_VERSION) {
// TLS 1.3 uses tickets as authenticators, so we are willing to use them for
// longer.
- session->timeout = ssl->session_ctx->session_psk_dhe_timeout;
+ session->timeout = hs->config->session_ctx->session_psk_dhe_timeout;
session->auth_timeout = SSL_DEFAULT_SESSION_AUTH_TIMEOUT;
} else {
// TLS 1.2 resumption does not incorporate new key material, so we use a
// much shorter timeout.
- session->timeout = ssl->session_ctx->session_timeout;
- session->auth_timeout = ssl->session_ctx->session_timeout;
+ session->timeout = hs->config->session_ctx->session_timeout;
+ session->auth_timeout = hs->config->session_ctx->session_timeout;
}
if (is_server) {
@@ -405,13 +405,13 @@
session->session_id_length = 0;
}
- if (ssl->cert->sid_ctx_length > sizeof(session->sid_ctx)) {
+ if (hs->config->cert->sid_ctx_length > sizeof(session->sid_ctx)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return 0;
}
- OPENSSL_memcpy(session->sid_ctx, ssl->cert->sid_ctx,
- ssl->cert->sid_ctx_length);
- session->sid_ctx_length = ssl->cert->sid_ctx_length;
+ OPENSSL_memcpy(session->sid_ctx, hs->config->cert->sid_ctx,
+ hs->config->cert->sid_ctx_length);
+ session->sid_ctx_length = hs->config->cert->sid_ctx_length;
// The session is marked not resumable until it is completely filled in.
session->not_resumable = 1;
@@ -475,7 +475,7 @@
return 1;
}
-static int ssl_encrypt_ticket_with_cipher_ctx(SSL *ssl, CBB *out,
+static int ssl_encrypt_ticket_with_cipher_ctx(SSL_HANDSHAKE *hs, CBB *out,
const uint8_t *session_buf,
size_t session_len) {
ScopedEVP_CIPHER_CTX ctx;
@@ -493,11 +493,11 @@
// Initialize HMAC and cipher contexts. If callback present it does all the
// work otherwise use generated values from parent ctx.
- SSL_CTX *tctx = ssl->session_ctx;
+ SSL_CTX *tctx = hs->config->session_ctx;
uint8_t iv[EVP_MAX_IV_LENGTH];
uint8_t key_name[16];
if (tctx->tlsext_ticket_key_cb != NULL) {
- if (tctx->tlsext_ticket_key_cb(ssl, key_name, iv, ctx.get(), hctx.get(),
+ if (tctx->tlsext_ticket_key_cb(hs->ssl, key_name, iv, ctx.get(), hctx.get(),
1 /* encrypt */) < 0) {
return 0;
}
@@ -554,11 +554,12 @@
return 1;
}
-static int ssl_encrypt_ticket_with_method(SSL *ssl, CBB *out,
+static int ssl_encrypt_ticket_with_method(SSL_HANDSHAKE *hs, CBB *out,
const uint8_t *session_buf,
size_t session_len) {
- const SSL_TICKET_AEAD_METHOD *method = ssl->session_ctx->ticket_aead_method;
- const size_t max_overhead = method->max_overhead(ssl);
+ const SSL_TICKET_AEAD_METHOD *method =
+ hs->config->session_ctx->ticket_aead_method;
+ const size_t max_overhead = method->max_overhead(hs->ssl);
const size_t max_out = session_len + max_overhead;
if (max_out < max_overhead) {
OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
@@ -571,7 +572,8 @@
}
size_t out_len;
- if (!method->seal(ssl, ptr, &out_len, max_out, session_buf, session_len)) {
+ if (!method->seal(hs->ssl, ptr, &out_len, max_out, session_buf,
+ session_len)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_TICKET_ENCRYPTION_FAILED);
return 0;
}
@@ -583,7 +585,8 @@
return 1;
}
-int ssl_encrypt_ticket(SSL *ssl, CBB *out, const SSL_SESSION *session) {
+int ssl_encrypt_ticket(SSL_HANDSHAKE *hs, CBB *out,
+ const SSL_SESSION *session) {
// Serialize the SSL_SESSION to be encoded into the ticket.
uint8_t *session_buf = NULL;
size_t session_len;
@@ -592,25 +595,25 @@
}
int ret = 0;
- if (ssl->session_ctx->ticket_aead_method) {
- ret = ssl_encrypt_ticket_with_method(ssl, out, session_buf, session_len);
+ if (hs->config->session_ctx->ticket_aead_method) {
+ ret = ssl_encrypt_ticket_with_method(hs, out, session_buf, session_len);
} else {
- ret =
- ssl_encrypt_ticket_with_cipher_ctx(ssl, out, session_buf, session_len);
+ ret = ssl_encrypt_ticket_with_cipher_ctx(hs, out, session_buf, session_len);
}
OPENSSL_free(session_buf);
return ret;
}
-int ssl_session_is_context_valid(const SSL *ssl, const SSL_SESSION *session) {
+int ssl_session_is_context_valid(const SSL_HANDSHAKE *hs,
+ const SSL_SESSION *session) {
if (session == NULL) {
return 0;
}
- return session->sid_ctx_length == ssl->cert->sid_ctx_length &&
- OPENSSL_memcmp(session->sid_ctx, ssl->cert->sid_ctx,
- ssl->cert->sid_ctx_length) == 0;
+ return session->sid_ctx_length == hs->config->cert->sid_ctx_length &&
+ OPENSSL_memcmp(session->sid_ctx, hs->config->cert->sid_ctx,
+ hs->config->cert->sid_ctx_length) == 0;
}
int ssl_session_is_time_valid(const SSL *ssl, const SSL_SESSION *session) {
@@ -632,14 +635,14 @@
int ssl_session_is_resumable(const SSL_HANDSHAKE *hs,
const SSL_SESSION *session) {
const SSL *const ssl = hs->ssl;
- return ssl_session_is_context_valid(ssl, session) &&
+ return ssl_session_is_context_valid(hs, session) &&
// The session must have been created by the same type of end point as
// we're now using it with.
ssl->server == session->is_server &&
// The session must not be expired.
ssl_session_is_time_valid(ssl, session) &&
/* Only resume if the session's version matches the negotiated
- * version. */
+ * version. */
ssl->version == session->ssl_version &&
// Only resume if the session's cipher matches the negotiated one.
hs->new_cipher == session->cipher &&
@@ -649,14 +652,14 @@
((sk_CRYPTO_BUFFER_num(session->certs) == 0 &&
!session->peer_sha256_valid) ||
session->peer_sha256_valid ==
- ssl->retain_only_sha256_of_client_certs);
+ hs->config->retain_only_sha256_of_client_certs);
}
// ssl_lookup_session looks up |session_id| in the session cache and sets
// |*out_session| to an |SSL_SESSION| object if found.
static enum ssl_hs_wait_t ssl_lookup_session(
- SSL *ssl, UniquePtr<SSL_SESSION> *out_session, const uint8_t *session_id,
- size_t session_id_len) {
+ SSL_HANDSHAKE *hs, UniquePtr<SSL_SESSION> *out_session,
+ const uint8_t *session_id, size_t session_id_len) {
out_session->reset();
if (session_id_len == 0 || session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) {
@@ -665,15 +668,16 @@
UniquePtr<SSL_SESSION> session;
// Try the internal cache, if it exists.
- if (!(ssl->session_ctx->session_cache_mode &
+ if (!(hs->config->session_ctx->session_cache_mode &
SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) {
SSL_SESSION data;
- data.ssl_version = ssl->version;
+ data.ssl_version = hs->ssl->version;
data.session_id_length = session_id_len;
OPENSSL_memcpy(data.session_id, session_id, session_id_len);
- MutexReadLock lock(&ssl->session_ctx->lock);
- session.reset(lh_SSL_SESSION_retrieve(ssl->session_ctx->sessions, &data));
+ MutexReadLock lock(&hs->config->session_ctx->lock);
+ session.reset(
+ lh_SSL_SESSION_retrieve(hs->config->session_ctx->sessions, &data));
if (session) {
// |lh_SSL_SESSION_retrieve| returns a non-owning pointer.
SSL_SESSION_up_ref(session.get());
@@ -682,10 +686,10 @@
}
// Fall back to the external cache, if it exists.
- if (!session && ssl->session_ctx->get_session_cb != nullptr) {
+ if (!session && hs->config->session_ctx->get_session_cb != nullptr) {
int copy = 1;
- session.reset(ssl->session_ctx->get_session_cb(ssl, session_id,
- session_id_len, ©));
+ session.reset(hs->config->session_ctx->get_session_cb(
+ hs->ssl, session_id, session_id_len, ©));
if (!session) {
return ssl_hs_ok;
}
@@ -704,15 +708,15 @@
}
// Add the externally cached session to the internal cache if necessary.
- if (!(ssl->session_ctx->session_cache_mode &
+ if (!(hs->config->session_ctx->session_cache_mode &
SSL_SESS_CACHE_NO_INTERNAL_STORE)) {
- SSL_CTX_add_session(ssl->session_ctx, session.get());
+ SSL_CTX_add_session(hs->config->session_ctx, session.get());
}
}
- if (session && !ssl_session_is_time_valid(ssl, session.get())) {
+ if (session && !ssl_session_is_time_valid(hs->ssl, session.get())) {
// The session was from the cache, so remove it.
- SSL_CTX_remove_session(ssl->session_ctx, session.get());
+ SSL_CTX_remove_session(hs->config->session_ctx, session.get());
session.reset();
}
@@ -720,13 +724,13 @@
return ssl_hs_ok;
}
-enum ssl_hs_wait_t ssl_get_prev_session(SSL *ssl,
+enum ssl_hs_wait_t ssl_get_prev_session(SSL_HANDSHAKE *hs,
UniquePtr<SSL_SESSION> *out_session,
bool *out_tickets_supported,
bool *out_renew_ticket,
const SSL_CLIENT_HELLO *client_hello) {
// This is used only by servers.
- assert(ssl->server);
+ assert(hs->ssl->server);
UniquePtr<SSL_SESSION> session;
bool renew_ticket = false;
@@ -734,12 +738,12 @@
const uint8_t *ticket = NULL;
size_t ticket_len = 0;
const bool tickets_supported =
- !(SSL_get_options(ssl) & SSL_OP_NO_TICKET) &&
- ssl->version > SSL3_VERSION &&
+ !(SSL_get_options(hs->ssl) & SSL_OP_NO_TICKET) &&
+ hs->ssl->version > SSL3_VERSION &&
SSL_early_callback_ctx_extension_get(
client_hello, TLSEXT_TYPE_session_ticket, &ticket, &ticket_len);
if (tickets_supported && ticket_len > 0) {
- switch (ssl_process_ticket(ssl, &session, &renew_ticket, ticket, ticket_len,
+ switch (ssl_process_ticket(hs, &session, &renew_ticket, ticket, ticket_len,
client_hello->session_id,
client_hello->session_id_len)) {
case ssl_ticket_aead_success:
@@ -755,7 +759,7 @@
} else {
// The client didn't send a ticket, so the session ID is a real ID.
enum ssl_hs_wait_t lookup_ret = ssl_lookup_session(
- ssl, &session, client_hello->session_id, client_hello->session_id_len);
+ hs, &session, client_hello->session_id, client_hello->session_id_len);
if (lookup_ret != ssl_hs_ok) {
return lookup_ret;
}
diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc
index 5fb4fb4..c7032af 100644
--- a/ssl/ssl_test.cc
+++ b/ssl/ssl_test.cc
@@ -1538,7 +1538,8 @@
bssl::UniquePtr<SSL> *out_server,
SSL_CTX *client_ctx, SSL_CTX *server_ctx,
const ClientConfig &config = ClientConfig(),
- bool do_handshake = true) {
+ bool do_handshake = true,
+ bool shed_handshake_config = true) {
bssl::UniquePtr<SSL> client(SSL_new(client_ctx)), server(SSL_new(server_ctx));
if (!client || !server) {
return false;
@@ -1562,6 +1563,9 @@
SSL_set_bio(client.get(), bio1, bio1);
SSL_set_bio(server.get(), bio2, bio2);
+ SSL_set_shed_handshake_config(client.get(), shed_handshake_config);
+ SSL_set_shed_handshake_config(server.get(), shed_handshake_config);
+
if (do_handshake && !CompleteHandshakes(client.get(), server.get())) {
return false;
}
@@ -1608,7 +1612,8 @@
bool Connect(const ClientConfig &config = ClientConfig()) {
return ConnectClientAndServer(&client_, &server_, client_ctx_.get(),
- server_ctx_.get(), config);
+ server_ctx_.get(), config, true,
+ shed_handshake_config_);
}
uint16_t version() const { return GetParam().version; }
@@ -1617,6 +1622,7 @@
return GetParam().ssl_method == VersionParam::is_dtls;
}
+ bool shed_handshake_config_ = true;
bssl::UniquePtr<SSL> client_, server_;
bssl::UniquePtr<SSL_CTX> server_ctx_, client_ctx_;
bssl::UniquePtr<X509> cert_;
@@ -2729,6 +2735,7 @@
return;
}
+ shed_handshake_config_ = false;
ASSERT_TRUE(Connect());
EXPECT_FALSE(SSL_session_reused(client_.get()));
@@ -2746,6 +2753,25 @@
EXPECT_TRUE(SSL_session_reused(server_.get()));
}
+TEST_P(SSLVersionTest, SSLClearFailsWithShedding) {
+ shed_handshake_config_ = false;
+ ASSERT_TRUE(Connect());
+ ASSERT_TRUE(CompleteHandshakes(client_.get(), server_.get()));
+
+ // Reset everything.
+ ASSERT_TRUE(SSL_clear(client_.get()));
+ ASSERT_TRUE(SSL_clear(server_.get()));
+
+ // Now enable shedding, and connect a second time.
+ shed_handshake_config_ = true;
+ ASSERT_TRUE(Connect());
+ ASSERT_TRUE(CompleteHandshakes(client_.get(), server_.get()));
+
+ // |SSL_clear| should now fail.
+ ASSERT_FALSE(SSL_clear(client_.get()));
+ ASSERT_FALSE(SSL_clear(server_.get()));
+}
+
static bool ChainsEqual(STACK_OF(X509) * chain,
const std::vector<X509 *> &expected) {
if (sk_X509_num(chain) != expected.size()) {
diff --git a/ssl/ssl_versions.cc b/ssl/ssl_versions.cc
index 73ea26f..0e28620 100644
--- a/ssl/ssl_versions.cc
+++ b/ssl/ssl_versions.cc
@@ -207,20 +207,20 @@
{TLS1_3_VERSION, SSL_OP_NO_TLSv1_3},
};
-bool ssl_get_version_range(const SSL *ssl, uint16_t *out_min_version,
+bool ssl_get_version_range(const SSL_HANDSHAKE *hs, uint16_t *out_min_version,
uint16_t *out_max_version) {
// For historical reasons, |SSL_OP_NO_DTLSv1| aliases |SSL_OP_NO_TLSv1|, but
// DTLS 1.0 should be mapped to TLS 1.1.
- uint32_t options = ssl->options;
- if (SSL_is_dtls(ssl)) {
+ uint32_t options = hs->ssl->options;
+ if (SSL_is_dtls(hs->ssl)) {
options &= ~SSL_OP_NO_TLSv1_1;
if (options & SSL_OP_NO_DTLSv1) {
options |= SSL_OP_NO_TLSv1_1;
}
}
- uint16_t min_version = ssl->conf_min_version;
- uint16_t max_version = ssl->conf_max_version;
+ uint16_t min_version = hs->config->conf_min_version;
+ uint16_t max_version = hs->config->conf_max_version;
// OpenSSL's API for controlling versions entails blacklisting individual
// protocols. This has two problems. First, on the client, the protocol can
@@ -373,11 +373,17 @@
}
int SSL_set_min_proto_version(SSL *ssl, uint16_t version) {
- return set_min_version(ssl->method, &ssl->conf_min_version, version);
+ if (!ssl->config) {
+ return 0;
+ }
+ return set_min_version(ssl->method, &ssl->config->conf_min_version, version);
}
int SSL_set_max_proto_version(SSL *ssl, uint16_t version) {
- return set_max_version(ssl->method, &ssl->conf_max_version, version);
+ if (!ssl->config) {
+ return 0;
+ }
+ return set_max_version(ssl->method, &ssl->config->conf_max_version, version);
}
int SSL_version(const SSL *ssl) {
diff --git a/ssl/ssl_x509.cc b/ssl/ssl_x509.cc
index cb35339..b9ea170 100644
--- a/ssl/ssl_x509.cc
+++ b/ssl/ssl_x509.cc
@@ -349,7 +349,7 @@
}
static int ssl_crypto_x509_session_verify_cert_chain(SSL_SESSION *session,
- SSL *ssl,
+ SSL_HANDSHAKE *hs,
uint8_t *out_alert) {
*out_alert = SSL_AD_INTERNAL_ERROR;
STACK_OF(X509) *const cert_chain = session->x509_chain;
@@ -357,9 +357,10 @@
return 0;
}
- X509_STORE *verify_store = ssl->ctx->cert_store;
- if (ssl->cert->verify_store != NULL) {
- verify_store = ssl->cert->verify_store;
+ SSL_CTX *ssl_ctx = hs->ssl->ctx;
+ X509_STORE *verify_store = ssl_ctx->cert_store;
+ if (hs->config->cert->verify_store != NULL) {
+ verify_store = hs->config->cert->verify_store;
}
X509 *leaf = sk_X509_value(cert_chain, 0);
@@ -368,8 +369,8 @@
OPENSSL_PUT_ERROR(SSL, ERR_R_X509_LIB);
return 0;
}
- if (!X509_STORE_CTX_set_ex_data(ctx.get(),
- SSL_get_ex_data_X509_STORE_CTX_idx(), ssl)) {
+ if (!X509_STORE_CTX_set_ex_data(
+ ctx.get(), SSL_get_ex_data_X509_STORE_CTX_idx(), hs->ssl)) {
return 0;
}
@@ -377,19 +378,20 @@
// context: if its a server it will verify SSL client certificates or vice
// versa.
X509_STORE_CTX_set_default(ctx.get(),
- ssl->server ? "ssl_client" : "ssl_server");
+ hs->ssl->server ? "ssl_client" : "ssl_server");
// Anything non-default in "param" should overwrite anything in the ctx.
- X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(ctx.get()), ssl->param);
+ X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(ctx.get()),
+ hs->config->param);
- if (ssl->verify_callback) {
- X509_STORE_CTX_set_verify_cb(ctx.get(), ssl->verify_callback);
+ if (hs->config->verify_callback) {
+ X509_STORE_CTX_set_verify_cb(ctx.get(), hs->config->verify_callback);
}
int verify_ret;
- if (ssl->ctx->app_verify_callback != NULL) {
+ if (ssl_ctx->app_verify_callback != NULL) {
verify_ret =
- ssl->ctx->app_verify_callback(ctx.get(), ssl->ctx->app_verify_arg);
+ ssl_ctx->app_verify_callback(ctx.get(), ssl_ctx->app_verify_arg);
} else {
verify_ret = X509_verify_cert(ctx.get());
}
@@ -397,7 +399,7 @@
session->verify_result = ctx->error;
// If |SSL_VERIFY_NONE|, the error is non-fatal, but we keep the result.
- if (verify_ret <= 0 && ssl->verify_mode != SSL_VERIFY_NONE) {
+ if (verify_ret <= 0 && hs->config->verify_mode != SSL_VERIFY_NONE) {
*out_alert = SSL_alert_from_verify_result(ctx->error);
return 0;
}
@@ -411,44 +413,45 @@
hs->cached_x509_ca_names = NULL;
}
-static int ssl_crypto_x509_ssl_new(SSL *ssl) {
- ssl->param = X509_VERIFY_PARAM_new();
- if (ssl->param == NULL) {
+static int ssl_crypto_x509_ssl_new(SSL_HANDSHAKE *hs) {
+ hs->config->param = X509_VERIFY_PARAM_new();
+ if (hs->config->param == NULL) {
return 0;
}
- X509_VERIFY_PARAM_inherit(ssl->param, ssl->ctx->param);
+ X509_VERIFY_PARAM_inherit(hs->config->param, hs->ssl->ctx->param);
return 1;
}
-static void ssl_crypto_x509_ssl_flush_cached_client_CA(SSL *ssl) {
- sk_X509_NAME_pop_free(ssl->cached_x509_client_CA, X509_NAME_free);
- ssl->cached_x509_client_CA = NULL;
+static void ssl_crypto_x509_ssl_flush_cached_client_CA(SSL_CONFIG *cfg) {
+ sk_X509_NAME_pop_free(cfg->cached_x509_client_CA, X509_NAME_free);
+ cfg->cached_x509_client_CA = NULL;
}
-static void ssl_crypto_x509_ssl_free(SSL *ssl) {
- ssl_crypto_x509_ssl_flush_cached_client_CA(ssl);
- X509_VERIFY_PARAM_free(ssl->param);
+static void ssl_crypto_x509_ssl_config_free(SSL_CONFIG *cfg) {
+ sk_X509_NAME_pop_free(cfg->cached_x509_client_CA, X509_NAME_free);
+ cfg->cached_x509_client_CA = NULL;
+ X509_VERIFY_PARAM_free(cfg->param);
}
-static int ssl_crypto_x509_ssl_auto_chain_if_needed(SSL *ssl) {
+static int ssl_crypto_x509_ssl_auto_chain_if_needed(SSL_HANDSHAKE *hs) {
// Only build a chain if there are no intermediates configured and the feature
// isn't disabled.
- if ((ssl->mode & SSL_MODE_NO_AUTO_CHAIN) ||
- !ssl_has_certificate(ssl) ||
- ssl->cert->chain == nullptr ||
- sk_CRYPTO_BUFFER_num(ssl->cert->chain.get()) > 1) {
+ if ((hs->ssl->mode & SSL_MODE_NO_AUTO_CHAIN) ||
+ !ssl_has_certificate(hs->config) || hs->config->cert->chain == NULL ||
+ sk_CRYPTO_BUFFER_num(hs->config->cert->chain.get()) > 1) {
return 1;
}
UniquePtr<X509> leaf(X509_parse_from_buffer(
- sk_CRYPTO_BUFFER_value(ssl->cert->chain.get(), 0)));
+ sk_CRYPTO_BUFFER_value(hs->config->cert->chain.get(), 0)));
if (!leaf) {
OPENSSL_PUT_ERROR(SSL, ERR_R_X509_LIB);
return 0;
}
ScopedX509_STORE_CTX ctx;
- if (!X509_STORE_CTX_init(ctx.get(), ssl->ctx->cert_store, leaf.get(), NULL)) {
+ if (!X509_STORE_CTX_init(ctx.get(), hs->ssl->ctx->cert_store, leaf.get(),
+ NULL)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_X509_LIB);
return 0;
}
@@ -460,11 +463,11 @@
// Remove the leaf from the generated chain.
X509_free(sk_X509_shift(ctx->chain));
- if (!ssl_cert_set_chain(ssl->cert, ctx->chain)) {
+ if (!ssl_cert_set_chain(hs->config->cert, ctx->chain)) {
return 0;
}
- ssl_crypto_x509_cert_flush_cached_chain(ssl->cert);
+ ssl_crypto_x509_cert_flush_cached_chain(hs->config->cert);
return 1;
}
@@ -499,7 +502,7 @@
ssl_crypto_x509_session_verify_cert_chain,
ssl_crypto_x509_hs_flush_cached_ca_names,
ssl_crypto_x509_ssl_new,
- ssl_crypto_x509_ssl_free,
+ ssl_crypto_x509_ssl_config_free,
ssl_crypto_x509_ssl_flush_cached_client_CA,
ssl_crypto_x509_ssl_auto_chain_if_needed,
ssl_crypto_x509_ssl_ctx_new,
@@ -578,7 +581,10 @@
int SSL_set_purpose(SSL *ssl, int purpose) {
check_ssl_x509_method(ssl);
- return X509_VERIFY_PARAM_set_purpose(ssl->param, purpose);
+ if (!ssl->config) {
+ return 0;
+ }
+ return X509_VERIFY_PARAM_set_purpose(ssl->config->param, purpose);
}
int SSL_CTX_set_trust(SSL_CTX *ctx, int trust) {
@@ -588,7 +594,10 @@
int SSL_set_trust(SSL *ssl, int trust) {
check_ssl_x509_method(ssl);
- return X509_VERIFY_PARAM_set_trust(ssl->param, trust);
+ if (!ssl->config) {
+ return 0;
+ }
+ return X509_VERIFY_PARAM_set_trust(ssl->config->param, trust);
}
int SSL_CTX_set1_param(SSL_CTX *ctx, const X509_VERIFY_PARAM *param) {
@@ -598,7 +607,10 @@
int SSL_set1_param(SSL *ssl, const X509_VERIFY_PARAM *param) {
check_ssl_x509_method(ssl);
- return X509_VERIFY_PARAM_set1(ssl->param, param);
+ if (!ssl->config) {
+ return 0;
+ }
+ return X509_VERIFY_PARAM_set1(ssl->config->param, param);
}
X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx) {
@@ -608,17 +620,29 @@
X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl) {
check_ssl_x509_method(ssl);
- return ssl->param;
+ if (!ssl->config) {
+ assert(ssl->config);
+ return 0;
+ }
+ return ssl->config->param;
}
int SSL_get_verify_depth(const SSL *ssl) {
check_ssl_x509_method(ssl);
- return X509_VERIFY_PARAM_get_depth(ssl->param);
+ if (!ssl->config) {
+ assert(ssl->config);
+ return 0;
+ }
+ return X509_VERIFY_PARAM_get_depth(ssl->config->param);
}
int (*SSL_get_verify_callback(const SSL *ssl))(int, X509_STORE_CTX *) {
check_ssl_x509_method(ssl);
- return ssl->verify_callback;
+ if (!ssl->config) {
+ assert(ssl->config);
+ return 0;
+ }
+ return ssl->config->verify_callback;
}
int SSL_CTX_get_verify_mode(const SSL_CTX *ctx) {
@@ -640,15 +664,21 @@
void SSL_set_verify(SSL *ssl, int mode,
int (*callback)(int ok, X509_STORE_CTX *store_ctx)) {
check_ssl_x509_method(ssl);
- ssl->verify_mode = mode;
+ if (!ssl->config) {
+ return;
+ }
+ ssl->config->verify_mode = mode;
if (callback != NULL) {
- ssl->verify_callback = callback;
+ ssl->config->verify_callback = callback;
}
}
void SSL_set_verify_depth(SSL *ssl, int depth) {
check_ssl_x509_method(ssl);
- X509_VERIFY_PARAM_set_depth(ssl->param, depth);
+ if (!ssl->config) {
+ return;
+ }
+ X509_VERIFY_PARAM_set_depth(ssl->config->param, depth);
}
void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx,
@@ -726,7 +756,10 @@
int SSL_use_certificate(SSL *ssl, X509 *x) {
check_ssl_x509_method(ssl);
- return ssl_use_certificate(ssl->cert, x);
+ if (!ssl->config) {
+ return 0;
+ }
+ return ssl_use_certificate(ssl->config->cert, x);
}
int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) {
@@ -764,7 +797,11 @@
X509 *SSL_get_certificate(const SSL *ssl) {
check_ssl_x509_method(ssl);
- return ssl_cert_get0_leaf(ssl->cert);
+ if (!ssl->config) {
+ assert(ssl->config);
+ return 0;
+ }
+ return ssl_cert_get0_leaf(ssl->config->cert);
}
X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx) {
@@ -846,12 +883,18 @@
int SSL_set0_chain(SSL *ssl, STACK_OF(X509) *chain) {
check_ssl_x509_method(ssl);
- return ssl_cert_set0_chain(ssl->cert, chain);
+ if (!ssl->config) {
+ return 0;
+ }
+ return ssl_cert_set0_chain(ssl->config->cert, chain);
}
int SSL_set1_chain(SSL *ssl, STACK_OF(X509) *chain) {
check_ssl_x509_method(ssl);
- return ssl_cert_set1_chain(ssl->cert, chain);
+ if (!ssl->config) {
+ return 0;
+ }
+ return ssl_cert_set1_chain(ssl->config->cert, chain);
}
int SSL_CTX_add0_chain_cert(SSL_CTX *ctx, X509 *x509) {
@@ -871,12 +914,18 @@
int SSL_add0_chain_cert(SSL *ssl, X509 *x509) {
check_ssl_x509_method(ssl);
- return ssl_cert_add0_chain_cert(ssl->cert, x509);
+ if (!ssl->config) {
+ return 0;
+ }
+ return ssl_cert_add0_chain_cert(ssl->config->cert, x509);
}
int SSL_add1_chain_cert(SSL *ssl, X509 *x509) {
check_ssl_x509_method(ssl);
- return ssl_cert_add1_chain_cert(ssl->cert, x509);
+ if (!ssl->config) {
+ return 0;
+ }
+ return ssl_cert_add1_chain_cert(ssl->config->cert, x509);
}
int SSL_CTX_clear_chain_certs(SSL_CTX *ctx) {
@@ -942,12 +991,16 @@
int SSL_get0_chain_certs(const SSL *ssl, STACK_OF(X509) **out_chain) {
check_ssl_x509_method(ssl);
- if (!ssl_cert_cache_chain_certs(ssl->cert)) {
+ if (!ssl->config) {
+ assert(ssl->config);
+ return 0;
+ }
+ if (!ssl_cert_cache_chain_certs(ssl->config->cert)) {
*out_chain = NULL;
return 0;
}
- *out_chain = ssl->cert->x509_chain;
+ *out_chain = ssl->config->cert->x509_chain;
return 1;
}
@@ -1022,8 +1075,11 @@
void SSL_set_client_CA_list(SSL *ssl, STACK_OF(X509_NAME) *name_list) {
check_ssl_x509_method(ssl);
- ssl->ctx->x509_method->ssl_flush_cached_client_CA(ssl);
- set_client_CA_list(&ssl->client_CA, name_list, ssl->ctx->pool);
+ if (!ssl->config) {
+ return;
+ }
+ ssl->ctx->x509_method->ssl_flush_cached_client_CA(ssl->config);
+ set_client_CA_list(&ssl->config->client_CA, name_list, ssl->ctx->pool);
sk_X509_NAME_pop_free(name_list, X509_NAME_free);
}
@@ -1068,6 +1124,10 @@
STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *ssl) {
check_ssl_x509_method(ssl);
+ if (!ssl->config) {
+ assert(ssl->config);
+ return NULL;
+ }
// For historical reasons, this function is used both to query configuration
// state on a server as well as handshake state on a client. However, whether
// |ssl| is a client or server is not known until explicitly configured with
@@ -1082,9 +1142,10 @@
return NULL;
}
- if (ssl->client_CA != NULL) {
+ if (ssl->config->client_CA != NULL) {
return buffer_names_to_x509(
- ssl->client_CA, (STACK_OF(X509_NAME) **)&ssl->cached_x509_client_CA);
+ ssl->config->client_CA,
+ (STACK_OF(X509_NAME) **)&ssl->config->cached_x509_client_CA);
}
return SSL_CTX_get_client_CA_list(ssl->ctx);
}
@@ -1140,11 +1201,14 @@
int SSL_add_client_CA(SSL *ssl, X509 *x509) {
check_ssl_x509_method(ssl);
- if (!add_client_CA(&ssl->client_CA, x509, ssl->ctx->pool)) {
+ if (!ssl->config) {
+ return 0;
+ }
+ if (!add_client_CA(&ssl->config->client_CA, x509, ssl->ctx->pool)) {
return 0;
}
- ssl_crypto_x509_ssl_flush_cached_client_CA(ssl);
+ ssl_crypto_x509_ssl_flush_cached_client_CA(ssl->config);
return 1;
}
@@ -1159,7 +1223,13 @@
}
static int do_client_cert_cb(SSL *ssl, void *arg) {
- if (ssl_has_certificate(ssl) || ssl->ctx->client_cert_cb == NULL) {
+ // Should only be called during handshake, but check to be sure.
+ if (!ssl->config) {
+ assert(ssl->config);
+ return -1;
+ }
+ if (ssl_has_certificate(ssl->config) ||
+ ssl->ctx->client_cert_cb == NULL) {
return 1;
}
@@ -1223,12 +1293,18 @@
int SSL_set0_verify_cert_store(SSL *ssl, X509_STORE *store) {
check_ssl_x509_method(ssl);
- return set_cert_store(&ssl->cert->verify_store, store, 0);
+ if (!ssl->config) {
+ return 0;
+ }
+ return set_cert_store(&ssl->config->cert->verify_store, store, 0);
}
int SSL_set1_verify_cert_store(SSL *ssl, X509_STORE *store) {
check_ssl_x509_method(ssl);
- return set_cert_store(&ssl->cert->verify_store, store, 1);
+ if (!ssl->config) {
+ return 0;
+ }
+ return set_cert_store(&ssl->config->cert->verify_store, store, 1);
}
int SSL_alert_from_verify_result(long result) {
diff --git a/ssl/t1_lib.cc b/ssl/t1_lib.cc
index a821246..eb6d90b 100644
--- a/ssl/t1_lib.cc
+++ b/ssl/t1_lib.cc
@@ -292,10 +292,10 @@
SSL_CURVE_SECP384R1,
};
-Span<const uint16_t> tls1_get_grouplist(const SSL *ssl) {
- if (ssl->supported_group_list != nullptr) {
- return MakeConstSpan(ssl->supported_group_list,
- ssl->supported_group_list_len);
+Span<const uint16_t> tls1_get_grouplist(const SSL_HANDSHAKE *hs) {
+ if (hs->config->supported_group_list != nullptr) {
+ return MakeConstSpan(hs->config->supported_group_list,
+ hs->config->supported_group_list_len);
}
return Span<const uint16_t>(kDefaultGroups);
}
@@ -313,7 +313,7 @@
// support our favoured group. Thus we do not special-case an emtpy
// |peer_supported_group_list|.
- Span<const uint16_t> groups = tls1_get_grouplist(ssl);
+ Span<const uint16_t> groups = tls1_get_grouplist(hs);
Span<const uint16_t> pref, supp;
if (ssl->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
pref = groups;
@@ -399,8 +399,8 @@
return 0;
}
-int tls1_check_group_id(const SSL *ssl, uint16_t group_id) {
- for (uint16_t supported : tls1_get_grouplist(ssl)) {
+int tls1_check_group_id(const SSL_HANDSHAKE *hs, uint16_t group_id) {
+ for (uint16_t supported : tls1_get_grouplist(hs)) {
if (supported == group_id) {
return 1;
}
@@ -1101,8 +1101,7 @@
// https://tools.ietf.org/html/rfc6066#section-8
static bool ext_ocsp_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
- SSL *const ssl = hs->ssl;
- if (!ssl->ocsp_stapling_enabled) {
+ if (!hs->config->ocsp_stapling_enabled) {
return true;
}
@@ -1166,8 +1165,7 @@
static bool ext_ocsp_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
SSL *const ssl = hs->ssl;
if (ssl_protocol_version(ssl) >= TLS1_3_VERSION ||
- !hs->ocsp_stapling_requested ||
- ssl->cert->ocsp_response == NULL ||
+ !hs->ocsp_stapling_requested || hs->config->cert->ocsp_response == NULL ||
ssl->s3->session_reused ||
!ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
return true;
@@ -1308,8 +1306,7 @@
// https://tools.ietf.org/html/rfc6962#section-3.3.1
static bool ext_sct_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
- SSL *const ssl = hs->ssl;
- if (!ssl->signed_cert_timestamps_enabled) {
+ if (!hs->config->signed_cert_timestamps_enabled) {
return true;
}
@@ -1336,7 +1333,7 @@
// If this is false then we should never have sent the SCT extension in the
// ClientHello and thus this function should never have been called.
- assert(ssl->signed_cert_timestamps_enabled);
+ assert(hs->config->signed_cert_timestamps_enabled);
if (!ssl_is_sct_list_valid(contents)) {
*out_alert = SSL_AD_DECODE_ERROR;
@@ -1378,9 +1375,8 @@
static bool ext_sct_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
SSL *const ssl = hs->ssl;
// The extension shouldn't be sent when resuming sessions.
- if (ssl_protocol_version(ssl) >= TLS1_3_VERSION ||
- ssl->s3->session_reused ||
- ssl->cert->signed_cert_timestamp_list == NULL) {
+ if (ssl_protocol_version(ssl) >= TLS1_3_VERSION || ssl->s3->session_reused ||
+ hs->config->cert->signed_cert_timestamp_list == NULL) {
return true;
}
@@ -1389,8 +1385,10 @@
CBB_add_u16_length_prefixed(out, &contents) &&
CBB_add_bytes(
&contents,
- CRYPTO_BUFFER_data(ssl->cert->signed_cert_timestamp_list.get()),
- CRYPTO_BUFFER_len(ssl->cert->signed_cert_timestamp_list.get())) &&
+ CRYPTO_BUFFER_data(
+ hs->config->cert->signed_cert_timestamp_list.get()),
+ CRYPTO_BUFFER_len(
+ hs->config->cert->signed_cert_timestamp_list.get())) &&
CBB_flush(out);
}
@@ -1401,7 +1399,7 @@
static bool ext_alpn_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
SSL *const ssl = hs->ssl;
- if (ssl->alpn_client_proto_list == NULL ||
+ if (hs->config->alpn_client_proto_list == NULL ||
ssl->s3->initial_handshake_complete) {
return true;
}
@@ -1410,8 +1408,8 @@
if (!CBB_add_u16(out, TLSEXT_TYPE_application_layer_protocol_negotiation) ||
!CBB_add_u16_length_prefixed(out, &contents) ||
!CBB_add_u16_length_prefixed(&contents, &proto_list) ||
- !CBB_add_bytes(&proto_list, ssl->alpn_client_proto_list,
- ssl->alpn_client_proto_list_len) ||
+ !CBB_add_bytes(&proto_list, hs->config->alpn_client_proto_list,
+ hs->config->alpn_client_proto_list_len) ||
!CBB_flush(out)) {
return false;
}
@@ -1427,7 +1425,7 @@
}
assert(!ssl->s3->initial_handshake_complete);
- assert(ssl->alpn_client_proto_list != NULL);
+ assert(hs->config->alpn_client_proto_list != NULL);
if (hs->next_proto_neg_seen) {
// NPN and ALPN may not be negotiated in the same connection.
@@ -1448,7 +1446,7 @@
return false;
}
- if (!ssl_is_alpn_protocol_allowed(ssl, protocol_name)) {
+ if (!ssl_is_alpn_protocol_allowed(hs, protocol_name)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_ALPN_PROTOCOL);
*out_alert = SSL_AD_ILLEGAL_PARAMETER;
return false;
@@ -1462,20 +1460,20 @@
return true;
}
-bool ssl_is_alpn_protocol_allowed(const SSL *ssl,
+bool ssl_is_alpn_protocol_allowed(const SSL_HANDSHAKE *hs,
Span<const uint8_t> protocol) {
- if (ssl->alpn_client_proto_list == nullptr) {
+ if (hs->config->alpn_client_proto_list == nullptr) {
return false;
}
- if (ssl->ctx->allow_unknown_alpn_protos) {
+ if (hs->ssl->ctx->allow_unknown_alpn_protos) {
return true;
}
// Check that the protocol name is one of the ones we advertised.
CBS client_protocol_name_list, client_protocol_name;
- CBS_init(&client_protocol_name_list, ssl->alpn_client_proto_list,
- ssl->alpn_client_proto_list_len);
+ CBS_init(&client_protocol_name_list, hs->config->alpn_client_proto_list,
+ hs->config->alpn_client_proto_list_len);
while (CBS_len(&client_protocol_name_list) > 0) {
if (!CBS_get_u8_length_prefixed(&client_protocol_name_list,
&client_protocol_name)) {
@@ -1575,8 +1573,7 @@
static bool ext_channel_id_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
SSL *const ssl = hs->ssl;
- if (!ssl->tlsext_channel_id_enabled ||
- SSL_is_dtls(ssl)) {
+ if (!hs->config->tlsext_channel_id_enabled || SSL_is_dtls(ssl)) {
return true;
}
@@ -1597,7 +1594,7 @@
}
assert(!SSL_is_dtls(ssl));
- assert(ssl->tlsext_channel_id_enabled);
+ assert(hs->config->tlsext_channel_id_enabled);
if (CBS_len(contents) != 0) {
return false;
@@ -1611,8 +1608,7 @@
uint8_t *out_alert,
CBS *contents) {
SSL *const ssl = hs->ssl;
- if (contents == NULL ||
- !ssl->tlsext_channel_id_enabled ||
+ if (contents == NULL || !hs->config->tlsext_channel_id_enabled ||
SSL_is_dtls(ssl)) {
return true;
}
@@ -2069,7 +2065,7 @@
static bool ext_early_data_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
SSL *const ssl = hs->ssl;
- if (!ssl->cert->enable_early_data ||
+ if (!ssl->enable_early_data ||
// Session must be 0-RTT capable.
ssl->session == NULL ||
ssl_session_protocol_version(ssl->session) < TLS1_3_VERSION ||
@@ -2080,8 +2076,8 @@
// avoid reporting a confusing value in |SSL_get0_alpn_selected|.
(ssl->session->early_alpn_len != 0 &&
!ssl_is_alpn_protocol_allowed(
- ssl, MakeConstSpan(ssl->session->early_alpn,
- ssl->session->early_alpn_len)))) {
+ hs, MakeConstSpan(ssl->session->early_alpn,
+ ssl->session->early_alpn_len)))) {
return true;
}
@@ -2191,7 +2187,7 @@
}
// Predict the most preferred group.
- Span<const uint16_t> groups = tls1_get_grouplist(ssl);
+ Span<const uint16_t> groups = tls1_get_grouplist(hs);
if (groups.empty()) {
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_GROUPS_SPECIFIED);
return false;
@@ -2422,7 +2418,7 @@
}
static bool ext_dummy_pq_padding_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
- const size_t len = hs->ssl->dummy_pq_padding_len;
+ const size_t len = hs->config->dummy_pq_padding_len;
if (len == 0) {
return true;
}
@@ -2437,7 +2433,7 @@
return true;
}
- if (CBS_len(contents) != hs->ssl->dummy_pq_padding_len) {
+ if (CBS_len(contents) != hs->config->dummy_pq_padding_len) {
return false;
}
@@ -2485,7 +2481,7 @@
return false;
}
- for (uint16_t group : tls1_get_grouplist(ssl)) {
+ for (uint16_t group : tls1_get_grouplist(hs)) {
if (!CBB_add_u16(&groups_bytes, group)) {
return false;
}
@@ -2556,7 +2552,7 @@
static bool ext_token_binding_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
SSL *const ssl = hs->ssl;
- if (ssl->token_binding_params == nullptr || SSL_is_dtls(ssl)) {
+ if (hs->config->token_binding_params == nullptr || SSL_is_dtls(ssl)) {
return true;
}
@@ -2565,8 +2561,8 @@
!CBB_add_u16_length_prefixed(out, &contents) ||
!CBB_add_u16(&contents, kTokenBindingMaxVersion) ||
!CBB_add_u8_length_prefixed(&contents, ¶ms) ||
- !CBB_add_bytes(¶ms, ssl->token_binding_params,
- ssl->token_binding_params_len) ||
+ !CBB_add_bytes(¶ms, hs->config->token_binding_params,
+ hs->config->token_binding_params_len) ||
!CBB_flush(out)) {
return false;
}
@@ -2606,8 +2602,8 @@
return true;
}
- for (size_t i = 0; i < ssl->token_binding_params_len; ++i) {
- if (param == ssl->token_binding_params[i]) {
+ for (size_t i = 0; i < hs->config->token_binding_params_len; ++i) {
+ if (param == hs->config->token_binding_params[i]) {
ssl->s3->negotiated_token_binding_param = param;
ssl->s3->token_binding_negotiated = true;
return true;
@@ -2619,15 +2615,16 @@
}
// select_tb_param looks for the first token binding param in
-// |ssl->token_binding_params| that is also in |params| and puts it in
-// |ssl->negotiated_token_binding_param|. It returns true if a token binding
+// |hs->ssl->token_binding_params| that is also in |params| and puts it in
+// |hs->ssl->negotiated_token_binding_param|. It returns true if a token binding
// param is found, and false otherwise.
-static bool select_tb_param(SSL *ssl, Span<const uint8_t> peer_params) {
- for (size_t i = 0; i < ssl->token_binding_params_len; ++i) {
- uint8_t tb_param = ssl->token_binding_params[i];
+static bool select_tb_param(SSL_HANDSHAKE *hs,
+ Span<const uint8_t> peer_params) {
+ for (size_t i = 0; i < hs->config->token_binding_params_len; ++i) {
+ uint8_t tb_param = hs->config->token_binding_params[i];
for (uint8_t peer_param : peer_params) {
if (tb_param == peer_param) {
- ssl->s3->negotiated_token_binding_param = tb_param;
+ hs->ssl->s3->negotiated_token_binding_param = tb_param;
return true;
}
}
@@ -2639,7 +2636,7 @@
uint8_t *out_alert,
CBS *contents) {
SSL *const ssl = hs->ssl;
- if (contents == nullptr || ssl->token_binding_params == nullptr) {
+ if (contents == nullptr || hs->config->token_binding_params == nullptr) {
return true;
}
@@ -2663,7 +2660,7 @@
// version. Otherwise, use the client's version.
hs->negotiated_token_binding_version =
std::min(version, kTokenBindingMaxVersion);
- if (!select_tb_param(ssl, params)) {
+ if (!select_tb_param(hs, params)) {
return true;
}
@@ -2695,16 +2692,15 @@
static bool ext_quic_transport_params_add_clienthello(SSL_HANDSHAKE *hs,
CBB *out) {
- SSL *const ssl = hs->ssl;
- if (!ssl->quic_transport_params || hs->max_version <= TLS1_2_VERSION) {
+ if (!hs->config->quic_transport_params || hs->max_version <= TLS1_2_VERSION) {
return true;
}
CBB contents;
if (!CBB_add_u16(out, TLSEXT_TYPE_quic_transport_parameters) ||
!CBB_add_u16_length_prefixed(out, &contents) ||
- !CBB_add_bytes(&contents, ssl->quic_transport_params,
- ssl->quic_transport_params_len) ||
+ !CBB_add_bytes(&contents, hs->config->quic_transport_params,
+ hs->config->quic_transport_params_len) ||
!CBB_flush(out)) {
return false;
}
@@ -2731,7 +2727,7 @@
uint8_t *out_alert,
CBS *contents) {
SSL *const ssl = hs->ssl;
- if (!contents || !ssl->quic_transport_params) {
+ if (!contents || !hs->config->quic_transport_params) {
return true;
}
// Ignore the extension before TLS 1.3.
@@ -2744,16 +2740,15 @@
static bool ext_quic_transport_params_add_serverhello(SSL_HANDSHAKE *hs,
CBB *out) {
- SSL *const ssl = hs->ssl;
- if (!ssl->quic_transport_params) {
+ if (!hs->config->quic_transport_params) {
return true;
}
CBB contents;
if (!CBB_add_u16(out, TLSEXT_TYPE_quic_transport_parameters) ||
!CBB_add_u16_length_prefixed(out, &contents) ||
- !CBB_add_bytes(&contents, ssl->quic_transport_params,
- ssl->quic_transport_params_len) ||
+ !CBB_add_bytes(&contents, hs->config->quic_transport_params,
+ hs->config->quic_transport_params_len) ||
!CBB_flush(out)) {
return false;
}
@@ -3322,9 +3317,9 @@
if (ssl->ctx->tlsext_servername_callback != 0) {
ret = ssl->ctx->tlsext_servername_callback(ssl, &al,
ssl->ctx->tlsext_servername_arg);
- } else if (ssl->session_ctx->tlsext_servername_callback != 0) {
- ret = ssl->session_ctx->tlsext_servername_callback(
- ssl, &al, ssl->session_ctx->tlsext_servername_arg);
+ } else if (hs->config->session_ctx->tlsext_servername_callback != 0) {
+ ret = hs->config->session_ctx->tlsext_servername_callback(
+ ssl, &al, hs->config->session_ctx->tlsext_servername_arg);
}
switch (ret) {
@@ -3407,14 +3402,14 @@
}
static enum ssl_ticket_aead_result_t ssl_decrypt_ticket_with_cb(
- SSL *ssl, uint8_t **out, size_t *out_len, bool *out_renew_ticket,
+ SSL_HANDSHAKE *hs, uint8_t **out, size_t *out_len, bool *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(),
+ int cb_ret = hs->config->session_ctx->tlsext_ticket_key_cb(
+ hs->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;
@@ -3430,10 +3425,10 @@
}
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,
+ SSL_HANDSHAKE *hs, 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;
+ SSL_CTX *ctx = hs->config->session_ctx;
// Rotate the ticket key if necessary.
if (!ssl_ctx_rotate_ticket_encryption_key(ctx)) {
@@ -3470,7 +3465,7 @@
}
static enum ssl_ticket_aead_result_t ssl_decrypt_ticket_with_method(
- SSL *ssl, uint8_t **out, size_t *out_len, bool *out_renew_ticket,
+ SSL_HANDSHAKE *hs, uint8_t **out, size_t *out_len, bool *out_renew_ticket,
const uint8_t *ticket, size_t ticket_len) {
uint8_t *plaintext = (uint8_t *)OPENSSL_malloc(ticket_len);
if (plaintext == NULL) {
@@ -3480,8 +3475,8 @@
size_t plaintext_len;
const enum ssl_ticket_aead_result_t result =
- ssl->session_ctx->ticket_aead_method->open(
- ssl, plaintext, &plaintext_len, ticket_len, ticket, ticket_len);
+ hs->config->session_ctx->ticket_aead_method->open(
+ hs->ssl, plaintext, &plaintext_len, ticket_len, ticket, ticket_len);
if (result == ssl_ticket_aead_success) {
*out = plaintext;
@@ -3494,13 +3489,13 @@
}
enum ssl_ticket_aead_result_t ssl_process_ticket(
- SSL *ssl, UniquePtr<SSL_SESSION> *out_session, bool *out_renew_ticket,
- const uint8_t *ticket, size_t ticket_len, const uint8_t *session_id,
- size_t session_id_len) {
+ SSL_HANDSHAKE *hs, UniquePtr<SSL_SESSION> *out_session,
+ bool *out_renew_ticket, const uint8_t *ticket, size_t ticket_len,
+ const uint8_t *session_id, size_t session_id_len) {
*out_renew_ticket = false;
out_session->reset();
- if ((SSL_get_options(ssl) & SSL_OP_NO_TICKET) ||
+ if ((SSL_get_options(hs->ssl) & SSL_OP_NO_TICKET) ||
session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) {
return ssl_ticket_aead_ignore_ticket;
}
@@ -3508,9 +3503,9 @@
uint8_t *plaintext = NULL;
size_t plaintext_len;
enum ssl_ticket_aead_result_t result;
- if (ssl->session_ctx->ticket_aead_method != NULL) {
+ if (hs->config->session_ctx->ticket_aead_method != NULL) {
result = ssl_decrypt_ticket_with_method(
- ssl, &plaintext, &plaintext_len, out_renew_ticket, ticket, ticket_len);
+ hs, &plaintext, &plaintext_len, out_renew_ticket, ticket, ticket_len);
} else {
// 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,
@@ -3519,12 +3514,12 @@
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,
+ if (hs->config->session_ctx->tlsext_ticket_key_cb != NULL) {
+ result = ssl_decrypt_ticket_with_cb(hs, &plaintext, &plaintext_len,
out_renew_ticket, ticket, ticket_len);
} else {
result = ssl_decrypt_ticket_with_ticket_keys(
- ssl, &plaintext, &plaintext_len, ticket, ticket_len);
+ hs, &plaintext, &plaintext_len, ticket, ticket_len);
}
}
@@ -3534,7 +3529,7 @@
// Decode the session.
UniquePtr<SSL_SESSION> session(
- SSL_SESSION_from_bytes(plaintext, plaintext_len, ssl->ctx));
+ SSL_SESSION_from_bytes(plaintext, plaintext_len, hs->ssl->ctx));
OPENSSL_free(plaintext);
if (!session) {
@@ -3575,7 +3570,7 @@
bool tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs, uint16_t *out) {
SSL *const ssl = hs->ssl;
- CERT *cert = ssl->cert;
+ CERT *cert = hs->config->cert;
// Before TLS 1.2, the signature algorithm isn't negotiated as part of the
// handshake.
@@ -3691,14 +3686,13 @@
}
bool tls1_write_channel_id(SSL_HANDSHAKE *hs, CBB *cbb) {
- SSL *const ssl = hs->ssl;
uint8_t digest[EVP_MAX_MD_SIZE];
size_t digest_len;
if (!tls1_channel_id_hash(hs, digest, &digest_len)) {
return false;
}
- EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(ssl->tlsext_channel_id_private);
+ EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(hs->config->tlsext_channel_id_private);
if (ec_key == nullptr) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return false;
@@ -3801,20 +3795,20 @@
return 1;
}
-int ssl_do_channel_id_callback(SSL *ssl) {
- if (ssl->tlsext_channel_id_private != NULL ||
- ssl->ctx->channel_id_cb == NULL) {
+int ssl_do_channel_id_callback(SSL_HANDSHAKE *hs) {
+ if (hs->config->tlsext_channel_id_private != NULL ||
+ hs->ssl->ctx->channel_id_cb == NULL) {
return 1;
}
EVP_PKEY *key = NULL;
- ssl->ctx->channel_id_cb(ssl, &key);
+ hs->ssl->ctx->channel_id_cb(hs->ssl, &key);
if (key == NULL) {
// The caller should try again later.
return 1;
}
- int ret = SSL_set1_tls_channel_id(ssl, key);
+ int ret = SSL_set1_tls_channel_id(hs->ssl, key);
EVP_PKEY_free(key);
return ret;
}
diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc
index f1531bd..dae759c 100644
--- a/ssl/test/bssl_shim.cc
+++ b/ssl/test/bssl_shim.cc
@@ -2066,11 +2066,14 @@
if (config->install_ddos_callback) {
SSL_CTX_set_dos_protection_cb(ssl_ctx, DDoSCallback);
}
+ SSL_set_shed_handshake_config(ssl.get(), true);
if (config->renegotiate_once) {
SSL_set_renegotiate_mode(ssl.get(), ssl_renegotiate_once);
+ SSL_set_shed_handshake_config(ssl.get(), config->shed_despite_renegotiate);
}
if (config->renegotiate_freely) {
SSL_set_renegotiate_mode(ssl.get(), ssl_renegotiate_freely);
+ SSL_set_shed_handshake_config(ssl.get(), config->shed_despite_renegotiate);
}
if (config->renegotiate_ignore) {
SSL_set_renegotiate_mode(ssl.get(), ssl_renegotiate_ignore);
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 866ad53..d85efca 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -8209,6 +8209,19 @@
},
})
+ // Renegotiation should be rejected if the handshake config has been shed.
+ testCases = append(testCases, testCase{
+ name: "Renegotiate-HandshakeConfigShed",
+ config: Config{
+ MaxVersion: VersionTLS12,
+ },
+ renegotiate: 1,
+ flags: []string{"-renegotiate-freely", "-shed-despite-renegotiate"},
+ shouldFail: true,
+ expectedError: ":NO_RENEGOTIATION:",
+ expectedLocalError: "remote error: no renegotiation",
+ })
+
// Renegotiation is not allowed at SSL 3.0.
testCases = append(testCases, testCase{
name: "Renegotiate-Client-SSL3",
diff --git a/ssl/test/test_config.cc b/ssl/test/test_config.cc
index f74267d..9433e4c 100644
--- a/ssl/test/test_config.cc
+++ b/ssl/test/test_config.cc
@@ -98,6 +98,7 @@
{ "-verify-peer", &TestConfig::verify_peer },
{ "-verify-peer-if-no-obc", &TestConfig::verify_peer_if_no_obc },
{ "-expect-verify-result", &TestConfig::expect_verify_result },
+ { "-shed-despite-renegotiate", &TestConfig::shed_despite_renegotiate },
{ "-renegotiate-once", &TestConfig::renegotiate_once },
{ "-renegotiate-freely", &TestConfig::renegotiate_freely },
{ "-renegotiate-ignore", &TestConfig::renegotiate_ignore },
diff --git a/ssl/test/test_config.h b/ssl/test/test_config.h
index 95f38e0..4a03fba 100644
--- a/ssl/test/test_config.h
+++ b/ssl/test/test_config.h
@@ -115,6 +115,7 @@
bool renegotiate_once = false;
bool renegotiate_freely = false;
bool renegotiate_ignore = false;
+ bool shed_despite_renegotiate = false;
int expect_peer_signature_algorithm = 0;
bool p384_only = false;
bool enable_all_curves = false;
diff --git a/ssl/tls13_both.cc b/ssl/tls13_both.cc
index defdac1..4cd3209 100644
--- a/ssl/tls13_both.cc
+++ b/ssl/tls13_both.cc
@@ -123,7 +123,7 @@
}
const bool retain_sha256 =
- ssl->server && ssl->retain_only_sha256_of_client_certs;
+ ssl->server && hs->config->retain_only_sha256_of_client_certs;
UniquePtr<EVP_PKEY> pkey;
while (CBS_len(&certificate_list) > 0) {
CBS certificate, extensions;
@@ -184,7 +184,7 @@
// All Certificate extensions are parsed, but only the leaf extensions are
// stored.
if (have_status_request) {
- if (ssl->server || !ssl->ocsp_stapling_enabled) {
+ if (ssl->server || !hs->config->ocsp_stapling_enabled) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION);
return 0;
@@ -213,7 +213,7 @@
}
if (have_sct) {
- if (ssl->server || !ssl->signed_cert_timestamps_enabled) {
+ if (ssl->server || !hs->config->signed_cert_timestamps_enabled) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION);
return 0;
@@ -363,11 +363,11 @@
return 0;
}
- if (!ssl_has_certificate(ssl)) {
+ if (!ssl_has_certificate(hs->config)) {
return ssl_add_message_cbb(ssl, cbb.get());
}
- CERT *cert = ssl->cert;
+ CERT *cert = hs->config->cert;
CRYPTO_BUFFER *leaf_buf = sk_CRYPTO_BUFFER_value(cert->chain.get(), 0);
CBB leaf, extensions;
if (!CBB_add_u24_length_prefixed(&certificate_list, &leaf) ||
@@ -378,30 +378,33 @@
return 0;
}
- if (hs->scts_requested && ssl->cert->signed_cert_timestamp_list != nullptr) {
+ if (hs->scts_requested &&
+ hs->config->cert->signed_cert_timestamp_list != nullptr) {
CBB contents;
if (!CBB_add_u16(&extensions, TLSEXT_TYPE_certificate_timestamp) ||
!CBB_add_u16_length_prefixed(&extensions, &contents) ||
!CBB_add_bytes(
&contents,
- CRYPTO_BUFFER_data(ssl->cert->signed_cert_timestamp_list.get()),
- CRYPTO_BUFFER_len(ssl->cert->signed_cert_timestamp_list.get())) ||
+ CRYPTO_BUFFER_data(
+ hs->config->cert->signed_cert_timestamp_list.get()),
+ CRYPTO_BUFFER_len(
+ hs->config->cert->signed_cert_timestamp_list.get())) ||
!CBB_flush(&extensions)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return 0;
}
}
- if (hs->ocsp_stapling_requested &&
- ssl->cert->ocsp_response != NULL) {
+ if (hs->ocsp_stapling_requested && hs->config->cert->ocsp_response != NULL) {
CBB contents, ocsp_response;
if (!CBB_add_u16(&extensions, TLSEXT_TYPE_status_request) ||
!CBB_add_u16_length_prefixed(&extensions, &contents) ||
!CBB_add_u8(&contents, TLSEXT_STATUSTYPE_ocsp) ||
!CBB_add_u24_length_prefixed(&contents, &ocsp_response) ||
- !CBB_add_bytes(&ocsp_response,
- CRYPTO_BUFFER_data(ssl->cert->ocsp_response.get()),
- CRYPTO_BUFFER_len(ssl->cert->ocsp_response.get())) ||
+ !CBB_add_bytes(
+ &ocsp_response,
+ CRYPTO_BUFFER_data(hs->config->cert->ocsp_response.get()),
+ CRYPTO_BUFFER_len(hs->config->cert->ocsp_response.get())) ||
!CBB_flush(&extensions)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return 0;
diff --git a/ssl/tls13_client.cc b/ssl/tls13_client.cc
index 6e328b8..3794043 100644
--- a/ssl/tls13_client.cc
+++ b/ssl/tls13_client.cc
@@ -157,7 +157,7 @@
}
// The group must be supported.
- if (!tls1_check_group_id(ssl, group_id)) {
+ if (!tls1_check_group_id(hs, group_id)) {
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
return ssl_hs_error;
@@ -316,7 +316,7 @@
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);
@@ -335,7 +335,7 @@
// Resumption incorporates fresh key material, so refresh the timeout.
ssl_session_renew_timeout(ssl, hs->new_session.get(),
- ssl->session_ctx->session_psk_dhe_timeout);
+ hs->config->session_ctx->session_psk_dhe_timeout);
} else if (!ssl_get_new_session(hs, 0)) {
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return ssl_hs_error;
@@ -629,8 +629,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);
@@ -652,9 +652,8 @@
}
static enum ssl_hs_wait_t do_send_client_certificate_verify(SSL_HANDSHAKE *hs) {
- SSL *const ssl = hs->ssl;
// Don't send CertificateVerify if there is no certificate.
- if (!ssl_has_certificate(ssl)) {
+ if (!ssl_has_certificate(hs->config)) {
hs->tls13_state = state_complete_second_flight;
return ssl_hs_ok;
}
@@ -681,12 +680,12 @@
// Send a Channel ID assertion if necessary.
if (ssl->s3->tlsext_channel_id_valid) {
- if (!ssl_do_channel_id_callback(ssl)) {
+ if (!ssl_do_channel_id_callback(hs)) {
hs->tls13_state = state_complete_second_flight;
return ssl_hs_error;
}
- if (ssl->tlsext_channel_id_private == NULL) {
+ if (hs->config->tlsext_channel_id_private == NULL) {
return ssl_hs_channel_id_lookup;
}
@@ -866,7 +865,7 @@
return 0;
}
- if (have_early_data_info && ssl->cert->enable_early_data) {
+ if (have_early_data_info && ssl->enable_early_data) {
if (!CBS_get_u32(&early_data_info, &session->ticket_max_early_data) ||
CBS_len(&early_data_info) != 0) {
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
diff --git a/ssl/tls13_server.cc b/ssl/tls13_server.cc
index fe0449d..5303f3f 100644
--- a/ssl/tls13_server.cc
+++ b/ssl/tls13_server.cc
@@ -169,7 +169,7 @@
return 0;
}
session->ticket_age_add_valid = 1;
- if (ssl->cert->enable_early_data) {
+ if (ssl->enable_early_data) {
session->ticket_max_early_data = kMaxEarlyDataAccepted;
}
@@ -186,12 +186,12 @@
!CBB_add_bytes(&nonce_cbb, nonce, sizeof(nonce)) ||
!CBB_add_u16_length_prefixed(&body, &ticket) ||
!tls13_derive_session_psk(session.get(), nonce) ||
- !ssl_encrypt_ticket(ssl, &ticket, session.get()) ||
+ !ssl_encrypt_ticket(hs, &ticket, session.get()) ||
!CBB_add_u16_length_prefixed(&body, &extensions)) {
return 0;
}
- if (ssl->cert->enable_early_data) {
+ if (ssl->enable_early_data) {
CBB early_data_info;
if (!CBB_add_u16(&extensions, TLSEXT_TYPE_early_data) ||
!CBB_add_u16_length_prefixed(&extensions, &early_data_info) ||
@@ -302,7 +302,7 @@
bool unused_renew;
UniquePtr<SSL_SESSION> session;
enum ssl_ticket_aead_result_t ret =
- ssl_process_ticket(ssl, &session, &unused_renew, CBS_data(&ticket),
+ ssl_process_ticket(hs, &session, &unused_renew, CBS_data(&ticket),
CBS_len(&ticket), NULL, 0);
switch (ret) {
case ssl_ticket_aead_success:
@@ -383,7 +383,7 @@
hs->new_session =
SSL_SESSION_dup(session.get(), SSL_SESSION_DUP_AUTH_ONLY);
- if (ssl->cert->enable_early_data &&
+ if (ssl->enable_early_data &&
// Early data must be acceptable for this ticket.
session->ticket_max_early_data != 0 &&
// The client must have offered early data.
@@ -408,8 +408,9 @@
ssl->s3->session_reused = true;
// Resumption incorporates fresh key material, so refresh the timeout.
- ssl_session_renew_timeout(ssl, hs->new_session.get(),
- ssl->session_ctx->session_psk_dhe_timeout);
+ ssl_session_renew_timeout(
+ ssl, hs->new_session.get(),
+ hs->config->session_ctx->session_psk_dhe_timeout);
break;
case ssl_ticket_aead_error:
@@ -599,9 +600,9 @@
if (!ssl->s3->session_reused) {
// Determine whether to request a client certificate.
- hs->cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
+ hs->cert_request = !!(hs->config->verify_mode & SSL_VERIFY_PEER);
// Only request a certificate if Channel ID isn't negotiated.
- if ((ssl->verify_mode & SSL_VERIFY_PEER_IF_NO_OBC) &&
+ if ((hs->config->verify_mode & SSL_VERIFY_PEER_IF_NO_OBC) &&
ssl->s3->tlsext_channel_id_valid) {
hs->cert_request = false;
}
@@ -635,13 +636,13 @@
}
}
- if (ssl_has_client_CAs(ssl)) {
+ if (ssl_has_client_CAs(hs->config)) {
CBB ca_contents;
if (!CBB_add_u16(&cert_request_extensions,
TLSEXT_TYPE_certificate_authorities) ||
!CBB_add_u16_length_prefixed(&cert_request_extensions,
&ca_contents) ||
- !ssl_add_client_CA_list(ssl, &ca_contents) ||
+ !ssl_add_client_CA_list(hs, &ca_contents) ||
!CBB_flush(&cert_request_extensions)) {
return ssl_hs_error;
}
@@ -654,7 +655,7 @@
// Send the server Certificate message, if necessary.
if (!ssl->s3->session_reused) {
- if (!ssl_has_certificate(ssl)) {
+ if (!ssl_has_certificate(hs->config)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
return ssl_hs_error;
}
@@ -805,7 +806,7 @@
}
const int allow_anonymous =
- (ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) == 0;
+ (hs->config->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) == 0;
SSLMessage msg;
if (!ssl->method->get_message(ssl, &msg)) {
return ssl_hs_read_message;
diff --git a/ssl/tls_method.cc b/ssl/tls_method.cc
index 2ad2817..d0adcdb 100644
--- a/ssl/tls_method.cc
+++ b/ssl/tls_method.cc
@@ -141,16 +141,18 @@
}
static void ssl_noop_x509_session_clear(SSL_SESSION *session) {}
static int ssl_noop_x509_session_verify_cert_chain(SSL_SESSION *session,
- SSL *ssl,
+ SSL_HANDSHAKE *hs,
uint8_t *out_alert) {
return 0;
}
static void ssl_noop_x509_hs_flush_cached_ca_names(SSL_HANDSHAKE *hs) {}
-static int ssl_noop_x509_ssl_new(SSL *ctx) { return 1; }
-static void ssl_noop_x509_ssl_free(SSL *ctx) { }
-static void ssl_noop_x509_ssl_flush_cached_client_CA(SSL *ssl) {}
-static int ssl_noop_x509_ssl_auto_chain_if_needed(SSL *ssl) { return 1; }
+static int ssl_noop_x509_ssl_new(SSL_HANDSHAKE *hs) { return 1; }
+static void ssl_noop_x509_ssl_config_free(SSL_CONFIG *cfg) {}
+static void ssl_noop_x509_ssl_flush_cached_client_CA(SSL_CONFIG *cfg) {}
+static int ssl_noop_x509_ssl_auto_chain_if_needed(SSL_HANDSHAKE *hs) {
+ return 1;
+}
static int ssl_noop_x509_ssl_ctx_new(SSL_CTX *ctx) { return 1; }
static void ssl_noop_x509_ssl_ctx_free(SSL_CTX *ctx) { }
static void ssl_noop_x509_ssl_ctx_flush_cached_client_CA(SSL_CTX *ctx) {}
@@ -168,7 +170,7 @@
ssl_noop_x509_session_verify_cert_chain,
ssl_noop_x509_hs_flush_cached_ca_names,
ssl_noop_x509_ssl_new,
- ssl_noop_x509_ssl_free,
+ ssl_noop_x509_ssl_config_free,
ssl_noop_x509_ssl_flush_cached_client_CA,
ssl_noop_x509_ssl_auto_chain_if_needed,
ssl_noop_x509_ssl_ctx_new,