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,