diff --git a/doc/man3/SSL_CTX_new.pod b/doc/man3/SSL_CTX_new.pod index f467f93659b575..bd24b53cd90d4c 100644 --- a/doc/man3/SSL_CTX_new.pod +++ b/doc/man3/SSL_CTX_new.pod @@ -3,7 +3,7 @@ =head1 NAME TLSv1_2_method, TLSv1_2_server_method, TLSv1_2_client_method, -SSL_CTX_new, SSL_CTX_new_ex, SSL_CTX_up_ref, SSLv3_method, +SSL_CTX_new, SSL_CTX_new_ex, SSL_CTX_dup, SSL_CTX_up_ref, SSLv3_method, SSLv3_server_method, SSLv3_client_method, TLSv1_method, TLSv1_server_method, TLSv1_client_method, TLSv1_1_method, TLSv1_1_server_method, TLSv1_1_client_method, TLS_method, TLS_server_method, TLS_client_method, @@ -21,6 +21,8 @@ functions SSL_CTX *SSL_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq, const SSL_METHOD *method); SSL_CTX *SSL_CTX_new(const SSL_METHOD *method); + SSL_CTX *SSL_CTX_dup(OSSL_LIB_CTX *libctx, SSL_CTX *source, + const char *propq, const SSL_METHOD *meth); int SSL_CTX_up_ref(SSL_CTX *ctx); const SSL_METHOD *TLS_method(void); @@ -88,6 +90,9 @@ parameters may be NULL. SSL_CTX_new() does the same as SSL_CTX_new_ex() except that the default library context is used and no property query string is specified. +SSL_CTX_dup() creates a new SSL_CTX object and uses the current configuration from +an existing SSL_CTX. + An B object is reference counted. Creating an B object for the first time increments the reference count. Freeing the B (using SSL_CTX_free) decrements it. When the reference count drops to zero, any memory diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c index 1ac0975d0a8faf..e24c69eb969c8f 100644 --- a/ssl/d1_lib.c +++ b/ssl/d1_lib.c @@ -629,13 +629,18 @@ int DTLSv1_listen(SSL *ssl, BIO_ADDR *client) /* * We have a cookie, so lets check it. */ - if (ssl->ctx->app_verify_cookie_cb == NULL) { + APP_VERIFY_COOKIE_CB verify_cookie_cb = NULL; + if (CRYPTO_THREAD_read_lock(ssl->ctx->cnf->cnf_lock)) { + verify_cookie_cb = ssl->ctx->cnf->app_verify_cookie_cb; + CRYPTO_THREAD_unlock(ssl->ctx->cnf->cnf_lock); + } + if (verify_cookie_cb == NULL) { ERR_raise(ERR_LIB_SSL, SSL_R_NO_VERIFY_COOKIE_CALLBACK); /* This is fatal */ ret = -1; goto end; } - if (ssl->ctx->app_verify_cookie_cb(ssl, PACKET_data(&cookiepkt), + if (verify_cookie_cb(ssl, PACKET_data(&cookiepkt), (unsigned int)PACKET_remaining(&cookiepkt)) == 0) { /* * We treat invalid cookies in the same was as no cookie as @@ -652,16 +657,20 @@ int DTLSv1_listen(SSL *ssl, BIO_ADDR *client) WPACKET wpkt; unsigned int version; size_t wreclen; - + APP_GEN_COOKIE_CB gen_cookie_cb = NULL; /* * There was no cookie in the ClientHello so we need to send a * HelloVerifyRequest. If this fails we do not worry about trying * to resend, we just drop it. */ + if (CRYPTO_THREAD_read_lock(ssl->ctx->cnf->cnf_lock)) { + gen_cookie_cb = ssl->ctx->cnf->app_gen_cookie_cb; + CRYPTO_THREAD_unlock(ssl->ctx->cnf->cnf_lock); + } /* Generate the cookie */ - if (ssl->ctx->app_gen_cookie_cb == NULL || - ssl->ctx->app_gen_cookie_cb(ssl, cookie, &cookielen) == 0 || + if (gen_cookie_cb == NULL || + gen_cookie_cb(ssl, cookie, &cookielen) == 0 || cookielen > 255) { ERR_raise(ERR_LIB_SSL, SSL_R_COOKIE_GEN_CALLBACK_FAILURE); /* This is fatal */ diff --git a/ssl/d1_msg.c b/ssl/d1_msg.c index b1e1fad16d9e47..a5c853825b1489 100644 --- a/ssl/d1_msg.c +++ b/ssl/d1_msg.c @@ -67,8 +67,13 @@ int dtls1_dispatch_alert(SSL *ssl) if (s->info_callback != NULL) cb = s->info_callback; - else if (ssl->ctx->info_callback != NULL) - cb = ssl->ctx->info_callback; + else { + if (CRYPTO_THREAD_read_lock(ssl->ctx->cnf->cnf_lock)) { + if (ssl->ctx->cnf->info_callback != NULL) + cb = ssl->ctx->cnf->info_callback; + CRYPTO_THREAD_unlock(ssl->ctx->cnf->cnf_lock); + } + } if (cb != NULL) { j = (s->s3.send_alert[0] << 8) | s->s3.send_alert[1]; diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c index 5306d6bd40a27b..f643e0c6ff2d39 100644 --- a/ssl/quic/quic_impl.c +++ b/ssl/quic/quic_impl.c @@ -423,8 +423,11 @@ SSL *ossl_quic_new(SSL_CTX *ctx) qc->as_server_state = qc->as_server; qc->default_stream_mode = SSL_DEFAULT_STREAM_MODE_AUTO_BIDI; - qc->default_ssl_mode = qc->ssl.ctx->mode; - qc->default_ssl_options = qc->ssl.ctx->options & OSSL_QUIC_PERMITTED_OPTIONS; + if (CRYPTO_THREAD_read_lock(qc->ssl.ctx->cnf->cnf_lock)) { + qc->default_ssl_mode = qc->ssl.ctx->cnf->mode; + qc->default_ssl_options = qc->ssl.ctx->cnf->options & OSSL_QUIC_PERMITTED_OPTIONS; + CRYPTO_THREAD_unlock(qc->ssl.ctx->cnf->cnf_lock); + } qc->desires_blocking = 1; qc->blocking = 0; qc->incoming_stream_policy = SSL_INCOMING_STREAM_POLICY_AUTO; @@ -433,8 +436,11 @@ SSL *ossl_quic_new(SSL_CTX *ctx) if (!create_channel(qc)) goto err; - ossl_quic_channel_set_msg_callback(qc->ch, ctx->msg_callback, ssl_base); - ossl_quic_channel_set_msg_callback_arg(qc->ch, ctx->msg_callback_arg); + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ossl_quic_channel_set_msg_callback(qc->ch, ctx->cnf->msg_callback, ssl_base); + ossl_quic_channel_set_msg_callback_arg(qc->ch, ctx->cnf->msg_callback_arg); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } qc_update_reject_policy(qc); diff --git a/ssl/quic/quic_tls.c b/ssl/quic/quic_tls.c index 25687db2fb628e..c383eba7384de3 100644 --- a/ssl/quic/quic_tls.c +++ b/ssl/quic/quic_tls.c @@ -742,7 +742,13 @@ int ossl_quic_tls_tick(QUIC_TLS *qtls) /* ALPN is a requirement for QUIC and must be set */ if (qtls->args.is_server) { - if (sctx->ext.alpn_select_cb == NULL) + int iserror = 0; + if (CRYPTO_THREAD_read_lock(sctx->cnf->cnf_lock)) { + if (sctx->cnf->ext.alpn_select_cb == NULL) + iserror = 1; + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + } + if (iserror == 1) return RAISE_INTERNAL_ERROR(qtls); } else { if (sc->ext.alpn == NULL || sc->ext.alpn_len == 0) diff --git a/ssl/record/rec_layer_d1.c b/ssl/record/rec_layer_d1.c index 87b588b84bed9d..f74291d6afcc6b 100644 --- a/ssl/record/rec_layer_d1.c +++ b/ssl/record/rec_layer_d1.c @@ -397,8 +397,13 @@ int dtls1_read_bytes(SSL *s, uint8_t type, uint8_t *recvd_type, if (sc->info_callback != NULL) cb = sc->info_callback; - else if (s->ctx->info_callback != NULL) - cb = s->ctx->info_callback; + else { + if (CRYPTO_THREAD_read_lock(s->ctx->cnf->cnf_lock)) { + if (s->ctx->cnf->info_callback != NULL) + cb = s->ctx->cnf->info_callback; + CRYPTO_THREAD_unlock(s->ctx->cnf->cnf_lock); + } + } if (cb != NULL) { j = (alert_level << 8) | alert_descr; diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c index 845eff9848e5b8..ff3b5475dfe698 100644 --- a/ssl/record/rec_layer_s3.c +++ b/ssl/record/rec_layer_s3.c @@ -156,7 +156,10 @@ size_t ssl3_pending(const SSL *s) void SSL_CTX_set_default_read_buffer_len(SSL_CTX *ctx, size_t len) { - ctx->default_read_buf_len = len; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->default_read_buf_len = len; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } void SSL_set_default_read_buffer_len(SSL *s, size_t len) @@ -823,8 +826,13 @@ int ssl3_read_bytes(SSL *ssl, uint8_t type, uint8_t *recvd_type, if (s->info_callback != NULL) cb = s->info_callback; - else if (ssl->ctx->info_callback != NULL) - cb = ssl->ctx->info_callback; + else { + if (CRYPTO_THREAD_read_lock(ssl->ctx->cnf->cnf_lock)) { + if (ssl->ctx->cnf->info_callback != NULL) + cb = ssl->ctx->cnf->info_callback; + CRYPTO_THREAD_unlock(ssl->ctx->cnf->cnf_lock); + } + } if (cb != NULL) { j = (alert_level << 8) | alert_descr; diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index d1497b115bc0c9..6116a48b884fcc 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -3818,6 +3818,7 @@ long ssl3_callback_ctrl(SSL *s, int cmd, void (*fp) (void)) long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) { + int rv = 0; switch (cmd) { #if !defined(OPENSSL_NO_DEPRECATED_3_0) case SSL_CTRL_SET_TMP_DH: @@ -3845,7 +3846,10 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) } #endif case SSL_CTRL_SET_DH_AUTO: - ctx->cert->dh_tmp_auto = larg; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->cert->dh_tmp_auto = larg; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } return 1; #if !defined(OPENSSL_NO_DEPRECATED_3_0) case SSL_CTRL_SET_TMP_ECDH: @@ -3854,21 +3858,32 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER); return 0; } - return ssl_set_tmp_ecdh_groups(&ctx->ext.supportedgroups, - &ctx->ext.supportedgroups_len, - parg); + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + rv = ssl_set_tmp_ecdh_groups(&ctx->cnf->ext.supportedgroups, + &ctx->cnf->ext.supportedgroups_len, + parg); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return rv; } #endif /* !OPENSSL_NO_DEPRECATED_3_0 */ case SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG: - ctx->ext.servername_arg = parg; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->ext.servername_arg = parg; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } break; case SSL_CTRL_SET_TLSEXT_TICKET_KEYS: case SSL_CTRL_GET_TLSEXT_TICKET_KEYS: { unsigned char *keys = parg; - long tick_keylen = (sizeof(ctx->ext.tick_key_name) + - sizeof(ctx->ext.secure->tick_hmac_key) + - sizeof(ctx->ext.secure->tick_aes_key)); + long tick_keylen = 0; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + tick_keylen = (sizeof(ctx->cnf->ext.tick_key_name) + + sizeof(ctx->cnf->ext.secure->tick_hmac_key) + + sizeof(ctx->cnf->ext.secure->tick_aes_key)); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } if (keys == NULL) return tick_keylen; if (larg != tick_keylen) { @@ -3876,46 +3891,68 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) return 0; } if (cmd == SSL_CTRL_SET_TLSEXT_TICKET_KEYS) { - memcpy(ctx->ext.tick_key_name, keys, - sizeof(ctx->ext.tick_key_name)); - memcpy(ctx->ext.secure->tick_hmac_key, - keys + sizeof(ctx->ext.tick_key_name), - sizeof(ctx->ext.secure->tick_hmac_key)); - memcpy(ctx->ext.secure->tick_aes_key, - keys + sizeof(ctx->ext.tick_key_name) + - sizeof(ctx->ext.secure->tick_hmac_key), - sizeof(ctx->ext.secure->tick_aes_key)); + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + memcpy(ctx->cnf->ext.tick_key_name, keys, + sizeof(ctx->cnf->ext.tick_key_name)); + memcpy(ctx->cnf->ext.secure->tick_hmac_key, + keys + sizeof(ctx->cnf->ext.tick_key_name), + sizeof(ctx->cnf->ext.secure->tick_hmac_key)); + memcpy(ctx->cnf->ext.secure->tick_aes_key, + keys + sizeof(ctx->cnf->ext.tick_key_name) + + sizeof(ctx->cnf->ext.secure->tick_hmac_key), + sizeof(ctx->cnf->ext.secure->tick_aes_key)); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } else { - memcpy(keys, ctx->ext.tick_key_name, - sizeof(ctx->ext.tick_key_name)); - memcpy(keys + sizeof(ctx->ext.tick_key_name), - ctx->ext.secure->tick_hmac_key, - sizeof(ctx->ext.secure->tick_hmac_key)); - memcpy(keys + sizeof(ctx->ext.tick_key_name) + - sizeof(ctx->ext.secure->tick_hmac_key), - ctx->ext.secure->tick_aes_key, - sizeof(ctx->ext.secure->tick_aes_key)); + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + memcpy(keys, ctx->cnf->ext.tick_key_name, + sizeof(ctx->cnf->ext.tick_key_name)); + memcpy(keys + sizeof(ctx->cnf->ext.tick_key_name), + ctx->cnf->ext.secure->tick_hmac_key, + sizeof(ctx->cnf->ext.secure->tick_hmac_key)); + memcpy(keys + sizeof(ctx->cnf->ext.tick_key_name) + + sizeof(ctx->cnf->ext.secure->tick_hmac_key), + ctx->cnf->ext.secure->tick_aes_key, + sizeof(ctx->cnf->ext.secure->tick_aes_key)); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } return 1; } case SSL_CTRL_GET_TLSEXT_STATUS_REQ_TYPE: - return ctx->ext.status_type; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + rv = ctx->cnf->ext.status_type; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return rv; case SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE: - ctx->ext.status_type = larg; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->ext.status_type = larg; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } break; case SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG: - ctx->ext.status_arg = parg; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->ext.status_arg = parg; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } return 1; case SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG: - *(void**)parg = ctx->ext.status_arg; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + *(void**)parg = ctx->cnf->ext.status_arg; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } break; case SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB: - *(int (**)(SSL*, void*))parg = ctx->ext.status_cb; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + *(int (**)(SSL*, void*))parg = ctx->cnf->ext.status_cb; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } break; #ifndef OPENSSL_NO_SRP @@ -3955,69 +3992,128 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) #endif case SSL_CTRL_SET_GROUPS: - return tls1_set_groups(&ctx->ext.supportedgroups, - &ctx->ext.supportedgroups_len, - parg, larg); + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + rv = tls1_set_groups(&ctx->cnf->ext.supportedgroups, + &ctx->cnf->ext.supportedgroups_len, + parg, larg); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return rv; case SSL_CTRL_SET_GROUPS_LIST: - return tls1_set_groups_list(ctx, &ctx->ext.supportedgroups, - &ctx->ext.supportedgroups_len, - parg); + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + rv =tls1_set_groups_list(ctx, &ctx->cnf->ext.supportedgroups, + &ctx->cnf->ext.supportedgroups_len, + parg); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return rv; case SSL_CTRL_SET_SIGALGS: - return tls1_set_sigalgs(ctx->cert, parg, larg, 0); + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + rv = tls1_set_sigalgs(ctx->cnf->cert, parg, larg, 0); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return rv; case SSL_CTRL_SET_SIGALGS_LIST: - return tls1_set_sigalgs_list(ctx->cert, parg, 0); + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + rv = tls1_set_sigalgs_list(ctx->cnf->cert, parg, 0); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return rv; case SSL_CTRL_SET_CLIENT_SIGALGS: - return tls1_set_sigalgs(ctx->cert, parg, larg, 1); + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + rv = tls1_set_sigalgs(ctx->cnf->cert, parg, larg, 1); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return rv; case SSL_CTRL_SET_CLIENT_SIGALGS_LIST: - return tls1_set_sigalgs_list(ctx->cert, parg, 1); + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + rv = tls1_set_sigalgs_list(ctx->cnf->cert, parg, 1); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return rv; case SSL_CTRL_SET_CLIENT_CERT_TYPES: - return ssl3_set_req_cert_type(ctx->cert, parg, larg); + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + rv = ssl3_set_req_cert_type(ctx->cnf->cert, parg, larg); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return rv; case SSL_CTRL_BUILD_CERT_CHAIN: - return ssl_build_cert_chain(NULL, ctx, larg); + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + rv = ssl_build_cert_chain(NULL, ctx, larg); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return rv; case SSL_CTRL_SET_VERIFY_CERT_STORE: - return ssl_cert_set_cert_store(ctx->cert, parg, 0, larg); + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + rv = ssl_cert_set_cert_store(ctx->cnf->cert, parg, 0, larg); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return rv; case SSL_CTRL_SET_CHAIN_CERT_STORE: - return ssl_cert_set_cert_store(ctx->cert, parg, 1, larg); + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + rv = ssl_cert_set_cert_store(ctx->cnf->cert, parg, 1, larg); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return rv; case SSL_CTRL_GET_VERIFY_CERT_STORE: - return ssl_cert_get_cert_store(ctx->cert, parg, 0); + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + rv = ssl_cert_get_cert_store(ctx->cnf->cert, parg, 0); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return rv; case SSL_CTRL_GET_CHAIN_CERT_STORE: - return ssl_cert_get_cert_store(ctx->cert, parg, 1); + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + rv = ssl_cert_get_cert_store(ctx->cnf->cert, parg, 1); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return rv; /* A Thawte special :-) */ case SSL_CTRL_EXTRA_CHAIN_CERT: - if (ctx->extra_certs == NULL) { - if ((ctx->extra_certs = sk_X509_new_null()) == NULL) { + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + if (ctx->cnf->extra_certs == NULL) { + if ((ctx->cnf->extra_certs = sk_X509_new_null()) == NULL) { + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB); + return 0; + } + } + if (!sk_X509_push(ctx->cnf->extra_certs, (X509 *)parg)) { + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB); return 0; } - } - if (!sk_X509_push(ctx->extra_certs, (X509 *)parg)) { - ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB); - return 0; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); } break; case SSL_CTRL_GET_EXTRA_CHAIN_CERTS: - if (ctx->extra_certs == NULL && larg == 0) - *(STACK_OF(X509) **)parg = ctx->cert->key->chain; - else - *(STACK_OF(X509) **)parg = ctx->extra_certs; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + if (ctx->cnf->extra_certs == NULL && larg == 0) + *(STACK_OF(X509) **)parg = ctx->cnf->cert->key->chain; + else + *(STACK_OF(X509) **)parg = ctx->cnf->extra_certs; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } break; case SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS: - OSSL_STACK_OF_X509_free(ctx->extra_certs); - ctx->extra_certs = NULL; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + OSSL_STACK_OF_X509_free(ctx->cnf->extra_certs); + ctx->cnf->extra_certs = NULL; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } break; case SSL_CTRL_CHAIN: @@ -4033,15 +4129,31 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) return ssl_cert_add0_chain_cert(NULL, ctx, (X509 *)parg); case SSL_CTRL_GET_CHAIN_CERTS: - *(STACK_OF(X509) **)parg = ctx->cert->key->chain; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + *(STACK_OF(X509) **)parg = ctx->cnf->cert->key->chain; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } break; case SSL_CTRL_SELECT_CURRENT_CERT: - return ssl_cert_select_current(ctx->cert, (X509 *)parg); + { + int rv = 0; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + rv = ssl_cert_select_current(ctx->cnf->cert, (X509 *)parg); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return rv; + } case SSL_CTRL_SET_CURRENT_CERT: - return ssl_cert_set_current(ctx->cert, larg); - + { + int rv = 0; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + rv = ssl_cert_set_current(ctx->cnf->cert, larg); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return rv; + } default: return 0; } @@ -4054,24 +4166,36 @@ long ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp) (void)) #if !defined(OPENSSL_NO_DEPRECATED_3_0) case SSL_CTRL_SET_TMP_DH_CB: { - ctx->cert->dh_tmp_cb = (DH *(*)(SSL *, int, int))fp; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->cert->dh_tmp_cb = (DH *(*)(SSL *, int, int))fp; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } break; #endif case SSL_CTRL_SET_TLSEXT_SERVERNAME_CB: - ctx->ext.servername_cb = (int (*)(SSL *, int *, void *))fp; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->ext.servername_cb = (int (*)(SSL *, int *, void *))fp; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } break; case SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB: - ctx->ext.status_cb = (int (*)(SSL *, void *))fp; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->ext.status_cb = (int (*)(SSL *, void *))fp; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } break; # ifndef OPENSSL_NO_DEPRECATED_3_0 case SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB: - ctx->ext.ticket_key_cb = (int (*)(SSL *, unsigned char *, - unsigned char *, - EVP_CIPHER_CTX *, - HMAC_CTX *, int))fp; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->ext.ticket_key_cb = (int (*)(SSL *, unsigned char *, + unsigned char *, + EVP_CIPHER_CTX *, + HMAC_CTX *, int))fp; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } break; #endif @@ -4093,7 +4217,10 @@ long ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp) (void)) #endif case SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB: { - ctx->not_resumable_session_cb = (int (*)(SSL *, int))fp; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->not_resumable_session_cb = (int (*)(SSL *, int))fp; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } break; default: @@ -4106,7 +4233,10 @@ int SSL_CTX_set_tlsext_ticket_key_evp_cb (SSL_CTX *ctx, int (*fp)(SSL *, unsigned char *, unsigned char *, EVP_CIPHER_CTX *, EVP_MAC_CTX *, int)) { - ctx->ext.ticket_key_evp_cb = fp; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->ext.ticket_key_evp_cb = fp; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } return 1; } diff --git a/ssl/s3_msg.c b/ssl/s3_msg.c index 3fcea15e279e4c..27f6141817e1cb 100644 --- a/ssl/s3_msg.c +++ b/ssl/s3_msg.c @@ -147,8 +147,13 @@ int ssl3_dispatch_alert(SSL *s) if (sc->info_callback != NULL) cb = sc->info_callback; - else if (s->ctx->info_callback != NULL) - cb = s->ctx->info_callback; + else { + if (CRYPTO_THREAD_read_lock(s->ctx->cnf->cnf_lock)) { + if (s->ctx->cnf->info_callback != NULL) + cb = s->ctx->cnf->info_callback; + CRYPTO_THREAD_unlock(s->ctx->cnf->cnf_lock); + } + } if (cb != NULL) { j = (sc->s3.send_alert[0] << 8) | sc->s3.send_alert[1]; diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c index f11eb75827dd80..5d7e7606b7917e 100644 --- a/ssl/ssl_cert.c +++ b/ssl/ssl_cert.c @@ -292,7 +292,16 @@ void ssl_cert_free(CERT *c) int ssl_cert_set0_chain(SSL_CONNECTION *s, SSL_CTX *ctx, STACK_OF(X509) *chain) { int i, r; - CERT_PKEY *cpk = s != NULL ? s->cert->key : ctx->cert->key; + CERT_PKEY *cpk = NULL; + + if (s != NULL) + cpk = s->cert->key; + else { + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + cpk = ctx->cnf->cert->key; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + } if (!cpk) return 0; @@ -329,7 +338,16 @@ int ssl_cert_set1_chain(SSL_CONNECTION *s, SSL_CTX *ctx, STACK_OF(X509) *chain) int ssl_cert_add0_chain_cert(SSL_CONNECTION *s, SSL_CTX *ctx, X509 *x) { int r; - CERT_PKEY *cpk = s ? s->cert->key : ctx->cert->key; + CERT_PKEY *cpk = NULL; + + if (s != NULL) + cpk = s->cert->key; + else { + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + cpk = ctx->cnf->cert->key; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + } if (!cpk) return 0; @@ -418,7 +436,7 @@ static int ssl_verify_internal(SSL_CONNECTION *s, STACK_OF(X509) *sk, EVP_PKEY * { X509 *x; int i = 0; - X509_STORE *verify_store; + X509_STORE *verify_store = NULL; X509_STORE_CTX *ctx = NULL; X509_VERIFY_PARAM *param; SSL_CTX *sctx; @@ -434,8 +452,12 @@ static int ssl_verify_internal(SSL_CONNECTION *s, STACK_OF(X509) *sk, EVP_PKEY * sctx = SSL_CONNECTION_GET_CTX(s); if (s->cert->verify_store) verify_store = s->cert->verify_store; - else - verify_store = sctx->cert_store; + else { + if (CRYPTO_THREAD_read_lock(sctx->cnf->cnf_lock)) { + verify_store = sctx->cnf->cert_store; + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + } + } ctx = X509_STORE_CTX_new_ex(sctx->libctx, sctx->propq); if (ctx == NULL) { @@ -490,8 +512,11 @@ static int ssl_verify_internal(SSL_CONNECTION *s, STACK_OF(X509) *sk, EVP_PKEY * if (s->verify_callback) X509_STORE_CTX_set_verify_cb(ctx, s->verify_callback); - if (sctx->app_verify_callback != NULL) { - i = sctx->app_verify_callback(ctx, sctx->app_verify_arg); + if (sctx->cnf->app_verify_callback != NULL) { + if (CRYPTO_THREAD_read_lock(sctx->cnf->cnf_lock)) { + i = sctx->cnf->app_verify_callback(ctx, sctx->cnf->app_verify_arg); + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + } } else { i = X509_verify_cert(ctx); /* We treat an error in the same way as a failure to verify */ @@ -586,32 +611,56 @@ void SSL_set0_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list) void SSL_CTX_set0_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list) { - set0_CA_list(&ctx->ca_names, name_list); + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + set0_CA_list(&ctx->cnf->ca_names, name_list); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } const STACK_OF(X509_NAME) *SSL_CTX_get0_CA_list(const SSL_CTX *ctx) { - return ctx->ca_names; + const STACK_OF(X509_NAME) *ret = NULL; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ctx->cnf->ca_names; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return ret; } const STACK_OF(X509_NAME) *SSL_get0_CA_list(const SSL *s) { const SSL_CONNECTION *sc = SSL_CONNECTION_FROM_CONST_SSL(s); + const STACK_OF(X509_NAME) *ret = NULL; if (sc == NULL) return NULL; - return sc->ca_names != NULL ? sc->ca_names : s->ctx->ca_names; + ret = sc->ca_names; + if (ret == NULL) { + if (CRYPTO_THREAD_read_lock(s->ctx->cnf->cnf_lock)) { + ret = s->ctx->cnf->ca_names; + CRYPTO_THREAD_unlock(s->ctx->cnf->cnf_lock); + } + } + return ret; } void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list) { - set0_CA_list(&ctx->client_ca_names, name_list); + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + set0_CA_list(&ctx->cnf->client_ca_names, name_list); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *ctx) { - return ctx->client_ca_names; + STACK_OF(X509_NAME) * ret = NULL; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ctx->cnf->client_ca_names; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return ret; } void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list) @@ -637,14 +686,22 @@ const STACK_OF(X509_NAME) *SSL_get0_peer_CA_list(const SSL *s) STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s) { const SSL_CONNECTION *sc = SSL_CONNECTION_FROM_CONST_SSL(s); + STACK_OF(X509_NAME) *ret = NULL; if (sc == NULL) return NULL; if (!sc->server) return sc->s3.tmp.peer_ca_names; - return sc->client_ca_names != NULL ? sc->client_ca_names - : s->ctx->client_ca_names; + + ret = sc->client_ca_names; + if (ret == NULL) { + if (CRYPTO_THREAD_read_lock(s->ctx->cnf->cnf_lock)) { + ret = s->ctx->cnf->client_ca_names; + CRYPTO_THREAD_unlock(s->ctx->cnf->cnf_lock); + } + } + return ret; } static int add_ca_name(STACK_OF(X509_NAME) **sk, const X509 *x) @@ -678,7 +735,12 @@ int SSL_add1_to_CA_list(SSL *ssl, const X509 *x) int SSL_CTX_add1_to_CA_list(SSL_CTX *ctx, const X509 *x) { - return add_ca_name(&ctx->ca_names, x); + int rv = 0; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + rv = add_ca_name(&ctx->cnf->ca_names, x); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return rv; } /* @@ -697,7 +759,12 @@ int SSL_add_client_CA(SSL *ssl, X509 *x) int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x) { - return add_ca_name(&ctx->client_ca_names, x); + int rv = 0; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + rv = add_ca_name(&ctx->cnf->client_ca_names, x); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return rv; } static int xname_cmp(const X509_NAME *a, const X509_NAME *b) @@ -987,8 +1054,8 @@ int SSL_add_store_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, /* Build a certificate chain for current certificate */ int ssl_build_cert_chain(SSL_CONNECTION *s, SSL_CTX *ctx, int flags) { - CERT *c = s != NULL ? s->cert : ctx->cert; - CERT_PKEY *cpk = c->key; + CERT *c = NULL; + CERT_PKEY *cpk = NULL; X509_STORE *chain_store = NULL; X509_STORE_CTX *xs_ctx = NULL; STACK_OF(X509) *chain = NULL, *untrusted = NULL; @@ -996,6 +1063,16 @@ int ssl_build_cert_chain(SSL_CONNECTION *s, SSL_CTX *ctx, int flags) SSL_CTX *real_ctx = (s == NULL) ? ctx : SSL_CONNECTION_GET_CTX(s); int i, rv = 0; + if (s != NULL) + c = s->cert; + else { + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + c = ctx->cnf->cert; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + } + cpk = c->key; + if (cpk->x509 == NULL) { ERR_raise(ERR_LIB_SSL, SSL_R_NO_CERTIFICATE_SET); goto err; @@ -1016,9 +1093,12 @@ int ssl_build_cert_chain(SSL_CONNECTION *s, SSL_CTX *ctx, int flags) } else { if (c->chain_store != NULL) chain_store = c->chain_store; - else - chain_store = real_ctx->cert_store; - + else { + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + chain_store = real_ctx->cnf->cert_store; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + } if (flags & SSL_BUILD_CHAIN_FLAG_UNTRUSTED) untrusted = cpk->chain; } @@ -1217,8 +1297,13 @@ int ssl_security(const SSL_CONNECTION *s, int op, int bits, int nid, void *other int ssl_ctx_security(const SSL_CTX *ctx, int op, int bits, int nid, void *other) { - return ctx->cert->sec_cb(NULL, ctx, op, bits, nid, other, - ctx->cert->sec_ex); + int rv = 0; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + rv = ctx->cnf->cert->sec_cb(NULL, ctx, op, bits, nid, other, + ctx->cnf->cert->sec_ex); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return rv; } int ssl_cert_lookup_by_nid(int nid, size_t *pidx, SSL_CTX *ctx) diff --git a/ssl/ssl_cert_comp.c b/ssl/ssl_cert_comp.c index 639610a5f77e2c..e9bbc1a94815e5 100644 --- a/ssl/ssl_cert_comp.c +++ b/ssl/ssl_cert_comp.c @@ -401,7 +401,10 @@ int SSL_CTX_compress_certs(SSL_CTX *ctx, int alg) if (new == NULL) return 0; - ret = ssl_compress_certs(new, ctx->cert->pkeys, alg); + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ssl_compress_certs(new, ctx->cnf->cert->pkeys, alg); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } SSL_free(new); #endif return ret; @@ -415,8 +418,12 @@ size_t SSL_get1_compressed_cert(SSL *ssl, int alg, unsigned char **data, size_t if (sc->cert != NULL) cpk = sc->cert->key; - else - cpk = ssl->ctx->cert->key; + else { + if (CRYPTO_THREAD_read_lock(ssl->ctx->cnf->cnf_lock)) { + cpk = ssl->ctx->cnf->cert->key; + CRYPTO_THREAD_unlock(ssl->ctx->cnf->cnf_lock); + } + } return ssl_get_compressed_cert(ssl, cpk, alg, data, orig_len); #else @@ -430,7 +437,10 @@ size_t SSL_CTX_get1_compressed_cert(SSL_CTX *ctx, int alg, unsigned char **data, size_t ret; SSL *new = SSL_new(ctx); - ret = ssl_get_compressed_cert(new, ctx->cert->key, alg, data, orig_len); + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ssl_get_compressed_cert(new, ctx->cnf->cert->key, alg, data, orig_len); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } SSL_free(new); return ret; #else @@ -441,11 +451,14 @@ size_t SSL_CTX_get1_compressed_cert(SSL_CTX *ctx, int alg, unsigned char **data, int SSL_CTX_set1_compressed_cert(SSL_CTX *ctx, int algorithm, unsigned char *comp_data, size_t comp_length, size_t orig_length) { + int ret = 0; #ifndef OPENSSL_NO_COMP_ALG - return ossl_set1_compressed_cert(ctx->cert, algorithm, comp_data, comp_length, orig_length); -#else - return 0; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ossl_set1_compressed_cert(ctx->cnf->cert, algorithm, comp_data, comp_length, orig_length); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } #endif + return ret; } int SSL_set1_compressed_cert(SSL *ssl, int algorithm, unsigned char *comp_data, diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c index 31c0d5af1dd57f..77ac6656ec3b8a 100644 --- a/ssl/ssl_ciph.c +++ b/ssl/ssl_ciph.c @@ -1423,11 +1423,15 @@ static int update_cipher_list(SSL_CTX *ctx, int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str) { - int ret = set_ciphersuites(&(ctx->tls13_ciphersuites), str); + int ret = 0; - if (ret && ctx->cipher_list != NULL) - return update_cipher_list(ctx, &ctx->cipher_list, &ctx->cipher_list_by_id, - ctx->tls13_ciphersuites); + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ret = set_ciphersuites(&(ctx->cnf->tls13_ciphersuites), str); + if (ret && ctx->cnf->cipher_list != NULL) + ret = update_cipher_list(ctx, &ctx->cnf->cipher_list, &ctx->cnf->cipher_list_by_id, + ctx->cnf->tls13_ciphersuites); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } return ret; } diff --git a/ssl/ssl_conf.c b/ssl/ssl_conf.c index 49e682247929b4..e95eb66e994ed4 100644 --- a/ssl/ssl_conf.c +++ b/ssl/ssl_conf.c @@ -438,7 +438,10 @@ static int cmd_Certificate(SSL_CONF_CTX *cctx, const char *value) CERT *c = NULL; if (cctx->ctx != NULL) { rv = SSL_CTX_use_certificate_chain_file(cctx->ctx, value); - c = cctx->ctx->cert; + if (CRYPTO_THREAD_read_lock(cctx->ctx->cnf->cnf_lock)) { + c = cctx->ctx->cnf->cert; + CRYPTO_THREAD_unlock(cctx->ctx->cnf->cnf_lock); + } } if (cctx->ssl != NULL) { SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(cctx->ssl); @@ -486,14 +489,17 @@ static int do_store(SSL_CONF_CTX *cctx, const char *CAfile, const char *CApath, const char *CAstore, int verify_store) { - CERT *cert; + CERT *cert = NULL; X509_STORE **st; SSL_CTX *ctx; OSSL_LIB_CTX *libctx = NULL; const char *propq = NULL; if (cctx->ctx != NULL) { - cert = cctx->ctx->cert; + if (CRYPTO_THREAD_read_lock(cctx->ctx->cnf->cnf_lock)) { + cert = cctx->ctx->cnf->cert; + CRYPTO_THREAD_unlock(cctx->ctx->cnf->cnf_lock); + } ctx = cctx->ctx; } else if (cctx->ssl != NULL) { SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(cctx->ssl); @@ -1015,7 +1021,10 @@ int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx) CERT *c = NULL; if (cctx->ctx != NULL) { - c = cctx->ctx->cert; + if (CRYPTO_THREAD_read_lock(cctx->ctx->cnf->cnf_lock)) { + c = cctx->ctx->cnf->cert; + CRYPTO_THREAD_unlock(cctx->ctx->cnf->cnf_lock); + } } else if (cctx->ssl != NULL) { SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(cctx->ssl); @@ -1115,11 +1124,14 @@ void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx) cctx->ctx = ctx; cctx->ssl = NULL; if (ctx) { - cctx->poptions = &ctx->options; - cctx->min_version = &ctx->min_proto_version; - cctx->max_version = &ctx->max_proto_version; - cctx->pcert_flags = &ctx->cert->cert_flags; - cctx->pvfy_flags = &ctx->verify_mode; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + cctx->poptions = &ctx->cnf->options; + cctx->min_version = &ctx->cnf->min_proto_version; + cctx->max_version = &ctx->cnf->max_proto_version; + cctx->pcert_flags = &ctx->cnf->cert->cert_flags; + cctx->pvfy_flags = &ctx->cnf->verify_mode; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } else { cctx->poptions = NULL; cctx->min_version = NULL; diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 13326d89256fff..a53c16a972d96f 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -683,7 +683,7 @@ int ossl_ssl_connection_reset(SSL *s) /** Used to change an SSL_CTXs default SSL method type */ int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth) { - STACK_OF(SSL_CIPHER) *sk; + STACK_OF(SSL_CIPHER) *sk = NULL; if (IS_QUIC_CTX(ctx)) { ERR_raise(ERR_LIB_SSL, SSL_R_WRONG_SSL_VERSION); @@ -696,11 +696,15 @@ int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth) ERR_raise(ERR_LIB_SSL, SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS); return 0; } - sk = ssl_create_cipher_list(ctx, - ctx->tls13_ciphersuites, - &(ctx->cipher_list), - &(ctx->cipher_list_by_id), - OSSL_default_cipher_list(), ctx->cert); + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + sk = ssl_create_cipher_list(ctx, + ctx->cnf->tls13_ciphersuites, + &(ctx->cnf->cipher_list), + &(ctx->cnf->cipher_list_by_id), + OSSL_default_cipher_list(), ctx->cnf->cert); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + if ((sk == NULL) || (sk_SSL_CIPHER_num(sk) <= 0)) { ERR_raise(ERR_LIB_SSL, SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS); return 0; @@ -754,6 +758,7 @@ SSL *ossl_ssl_connection_new_int(SSL_CTX *ctx, const SSL_METHOD *method) { SSL_CONNECTION *s; SSL *ssl; + int rv = 0; s = OPENSSL_zalloc(sizeof(*s)); if (s == NULL) @@ -769,128 +774,145 @@ SSL *ossl_ssl_connection_new_int(SSL_CTX *ctx, const SSL_METHOD *method) RECORD_LAYER_init(&s->rlayer, s); - s->options = ctx->options; - - s->dane.flags = ctx->dane.flags; - if (method->version == ctx->method->version) { - s->min_proto_version = ctx->min_proto_version; - s->max_proto_version = ctx->max_proto_version; - } - - s->mode = ctx->mode; - s->max_cert_list = ctx->max_cert_list; - s->max_early_data = ctx->max_early_data; - s->recv_max_early_data = ctx->recv_max_early_data; - - s->num_tickets = ctx->num_tickets; - s->pha_enabled = ctx->pha_enabled; - - /* Shallow copy of the ciphersuites stack */ - s->tls13_ciphersuites = sk_SSL_CIPHER_dup(ctx->tls13_ciphersuites); - if (s->tls13_ciphersuites == NULL) - goto cerr; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + s->options = ctx->cnf->options; + s->dane.flags = ctx->dane.flags; + if (method->version == ctx->method->version) { + s->min_proto_version = ctx->cnf->min_proto_version; + s->max_proto_version = ctx->cnf->max_proto_version; + } + s->mode = ctx->cnf->mode; + s->max_cert_list = ctx->cnf->max_cert_list; + s->max_early_data = ctx->cnf->max_early_data; + s->recv_max_early_data = ctx->cnf->recv_max_early_data; + s->num_tickets = ctx->cnf->num_tickets; + s->pha_enabled = ctx->cnf->pha_enabled; + + /* Shallow copy of the ciphersuites stack */ + s->tls13_ciphersuites = sk_SSL_CIPHER_dup(ctx->cnf->tls13_ciphersuites); + + if (s->tls13_ciphersuites == NULL) { + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + goto cerr; + } - /* - * Earlier library versions used to copy the pointer to the CERT, not - * its contents; only when setting new parameters for the per-SSL - * copy, ssl_cert_new would be called (and the direct reference to - * the per-SSL_CTX settings would be lost, but those still were - * indirectly accessed for various purposes, and for that reason they - * used to be known as s->ctx->default_cert). Now we don't look at the - * SSL_CTX's CERT after having duplicated it once. - */ - s->cert = ssl_cert_dup(ctx->cert); - if (s->cert == NULL) - goto sslerr; + /* + * Earlier library versions used to copy the pointer to the CERT, not + * its contents; only when setting new parameters for the per-SSL + * copy, ssl_cert_new would be called (and the direct reference to + * the per-SSL_CTX settings would be lost, but those still were + * indirectly accessed for various purposes, and for that reason they + * used to be known as s->ctx->default_cert). Now we don't look at the + * SSL_CTX's CERT after having duplicated it once. + */ + s->cert = ssl_cert_dup(ctx->cnf->cert); + if (s->cert == NULL) { + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + goto sslerr; + } - RECORD_LAYER_set_read_ahead(&s->rlayer, ctx->read_ahead); - s->msg_callback = ctx->msg_callback; - s->msg_callback_arg = ctx->msg_callback_arg; - s->verify_mode = ctx->verify_mode; - s->not_resumable_session_cb = ctx->not_resumable_session_cb; - s->rlayer.record_padding_cb = ctx->record_padding_cb; - s->rlayer.record_padding_arg = ctx->record_padding_arg; - s->rlayer.block_padding = ctx->block_padding; - s->sid_ctx_length = ctx->sid_ctx_length; - if (!ossl_assert(s->sid_ctx_length <= sizeof(s->sid_ctx))) - goto err; - memcpy(&s->sid_ctx, &ctx->sid_ctx, sizeof(s->sid_ctx)); - s->verify_callback = ctx->default_verify_callback; - s->generate_session_id = ctx->generate_session_id; - - s->param = X509_VERIFY_PARAM_new(); - if (s->param == NULL) - goto asn1err; - X509_VERIFY_PARAM_inherit(s->param, ctx->param); - s->quiet_shutdown = IS_QUIC_CTX(ctx) ? 0 : ctx->quiet_shutdown; - - if (!IS_QUIC_CTX(ctx)) - s->ext.max_fragment_len_mode = ctx->ext.max_fragment_len_mode; - - s->max_send_fragment = ctx->max_send_fragment; - s->split_send_fragment = ctx->split_send_fragment; - s->max_pipelines = ctx->max_pipelines; - s->rlayer.default_read_buf_len = ctx->default_read_buf_len; - - s->ext.debug_cb = 0; - s->ext.debug_arg = NULL; - s->ext.ticket_expected = 0; - s->ext.status_type = ctx->ext.status_type; - s->ext.status_expected = 0; - s->ext.ocsp.ids = NULL; - s->ext.ocsp.exts = NULL; - s->ext.ocsp.resp = NULL; - s->ext.ocsp.resp_len = 0; - SSL_CTX_up_ref(ctx); - s->session_ctx = ctx; - if (ctx->ext.ecpointformats) { - s->ext.ecpointformats = - OPENSSL_memdup(ctx->ext.ecpointformats, - ctx->ext.ecpointformats_len); - if (!s->ext.ecpointformats) { - s->ext.ecpointformats_len = 0; + RECORD_LAYER_set_read_ahead(&s->rlayer, ctx->cnf->read_ahead); + s->msg_callback = ctx->cnf->msg_callback; + s->msg_callback_arg = ctx->cnf->msg_callback_arg; + s->verify_mode = ctx->cnf->verify_mode; + s->not_resumable_session_cb = ctx->cnf->not_resumable_session_cb; + s->rlayer.record_padding_cb = ctx->cnf->record_padding_cb; + s->rlayer.record_padding_arg = ctx->cnf->record_padding_arg; + s->rlayer.block_padding = ctx->cnf->block_padding; + s->sid_ctx_length = ctx->cnf->sid_ctx_length; + if (!ossl_assert(s->sid_ctx_length <= sizeof(s->sid_ctx))) { + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); goto err; } - s->ext.ecpointformats_len = - ctx->ext.ecpointformats_len; - } - if (ctx->ext.supportedgroups) { - s->ext.supportedgroups = - OPENSSL_memdup(ctx->ext.supportedgroups, - ctx->ext.supportedgroups_len - * sizeof(*ctx->ext.supportedgroups)); - if (!s->ext.supportedgroups) { - s->ext.supportedgroups_len = 0; - goto err; + memcpy(&s->sid_ctx, &ctx->cnf->sid_ctx, sizeof(s->sid_ctx)); + s->verify_callback = ctx->cnf->default_verify_callback; + s->generate_session_id = ctx->cnf->generate_session_id; + + s->param = X509_VERIFY_PARAM_new(); + if (s->param == NULL) { + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + goto asn1err; + } + + X509_VERIFY_PARAM_inherit(s->param, ctx->cnf->param); + s->quiet_shutdown = IS_QUIC_CTX(ctx) ? 0 : ctx->cnf->quiet_shutdown; + + if (!IS_QUIC_CTX(ctx)) + s->ext.max_fragment_len_mode = ctx->cnf->ext.max_fragment_len_mode; + + s->max_send_fragment = ctx->cnf->max_send_fragment; + s->split_send_fragment = ctx->cnf->split_send_fragment; + s->max_pipelines = ctx->cnf->max_pipelines; + s->rlayer.default_read_buf_len = ctx->cnf->default_read_buf_len; + + s->ext.debug_cb = 0; + s->ext.debug_arg = NULL; + s->ext.ticket_expected = 0; + s->ext.status_type = ctx->cnf->ext.status_type; + s->ext.status_expected = 0; + s->ext.ocsp.ids = NULL; + s->ext.ocsp.exts = NULL; + s->ext.ocsp.resp = NULL; + s->ext.ocsp.resp_len = 0; + SSL_CTX_up_ref(ctx); + s->session_ctx = ctx; + + if (ctx->cnf->ext.ecpointformats) { + s->ext.ecpointformats = + OPENSSL_memdup(ctx->cnf->ext.ecpointformats, + ctx->cnf->ext.ecpointformats_len); + if (!s->ext.ecpointformats) { + s->ext.ecpointformats_len = 0; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + goto err; + } + s->ext.ecpointformats_len = + ctx->cnf->ext.ecpointformats_len; + } + if (ctx->cnf->ext.supportedgroups) { + s->ext.supportedgroups = + OPENSSL_memdup(ctx->cnf->ext.supportedgroups, + ctx->cnf->ext.supportedgroups_len + * sizeof(*ctx->cnf->ext.supportedgroups)); + if (!s->ext.supportedgroups) { + s->ext.supportedgroups_len = 0; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + goto err; + } + s->ext.supportedgroups_len = ctx->cnf->ext.supportedgroups_len; } - s->ext.supportedgroups_len = ctx->ext.supportedgroups_len; - } #ifndef OPENSSL_NO_NEXTPROTONEG - s->ext.npn = NULL; + s->ext.npn = NULL; #endif - if (ctx->ext.alpn != NULL) { - s->ext.alpn = OPENSSL_malloc(ctx->ext.alpn_len); - if (s->ext.alpn == NULL) { - s->ext.alpn_len = 0; - goto err; + if (ctx->cnf->ext.alpn != NULL) { + s->ext.alpn = OPENSSL_malloc(ctx->cnf->ext.alpn_len); + if (s->ext.alpn == NULL) { + s->ext.alpn_len = 0; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + goto err; + } + memcpy(s->ext.alpn, ctx->cnf->ext.alpn, ctx->cnf->ext.alpn_len); + s->ext.alpn_len = ctx->cnf->ext.alpn_len; } - memcpy(s->ext.alpn, ctx->ext.alpn, ctx->ext.alpn_len); - s->ext.alpn_len = ctx->ext.alpn_len; - } - s->verified_chain = NULL; - s->verify_result = X509_V_OK; + s->verified_chain = NULL; + s->verify_result = X509_V_OK; - s->default_passwd_callback = ctx->default_passwd_callback; - s->default_passwd_callback_userdata = ctx->default_passwd_callback_userdata; + s->default_passwd_callback = ctx->cnf->default_passwd_callback; + s->default_passwd_callback_userdata = ctx->cnf->default_passwd_callback_userdata; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } s->key_update = SSL_KEY_UPDATE_NONE; if (!IS_QUIC_CTX(ctx)) { - s->allow_early_data_cb = ctx->allow_early_data_cb; - s->allow_early_data_cb_data = ctx->allow_early_data_cb_data; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + s->allow_early_data_cb = ctx->cnf->allow_early_data_cb; + s->allow_early_data_cb_data = ctx->cnf->allow_early_data_cb_data; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } if (!method->ssl_init(ssl)) @@ -901,15 +923,18 @@ SSL *ossl_ssl_connection_new_int(SSL_CTX *ctx, const SSL_METHOD *method) if (!method->ssl_reset(ssl)) goto sslerr; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { #ifndef OPENSSL_NO_PSK - s->psk_client_callback = ctx->psk_client_callback; - s->psk_server_callback = ctx->psk_server_callback; + s->psk_client_callback = ctx->cnf->psk_client_callback; + s->psk_server_callback = ctx->cnf->psk_server_callback; #endif - s->psk_find_session_cb = ctx->psk_find_session_cb; - s->psk_use_session_cb = ctx->psk_use_session_cb; + s->psk_find_session_cb = ctx->cnf->psk_find_session_cb; + s->psk_use_session_cb = ctx->cnf->psk_use_session_cb; - s->async_cb = ctx->async_cb; - s->async_cb_arg = ctx->async_cb_arg; + s->async_cb = ctx->cnf->async_cb; + s->async_cb_arg = ctx->cnf->async_cb_arg; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } s->job = NULL; @@ -932,8 +957,13 @@ SSL *ossl_ssl_connection_new_int(SSL_CTX *ctx, const SSL_METHOD *method) } #ifndef OPENSSL_NO_CT - if (!SSL_set_ct_validation_callback(ssl, ctx->ct_validation_callback, - ctx->ct_validation_callback_arg)) + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + rv = SSL_set_ct_validation_callback(ssl, ctx->cnf->ct_validation_callback, + ctx->cnf->ct_validation_callback_arg); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + + if (!rv) goto sslerr; #endif @@ -1015,8 +1045,12 @@ int SSL_CTX_set_session_id_context(SSL_CTX *ctx, const unsigned char *sid_ctx, ERR_raise(ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); return 0; } - ctx->sid_ctx_length = sid_ctx_len; - memcpy(ctx->sid_ctx, sid_ctx, sid_ctx_len); + + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->sid_ctx_length = sid_ctx_len; + memcpy(ctx->cnf->sid_ctx, sid_ctx, sid_ctx_len); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } return 1; } @@ -1041,11 +1075,12 @@ int SSL_set_session_id_context(SSL *ssl, const unsigned char *sid_ctx, int SSL_CTX_set_generate_session_id(SSL_CTX *ctx, GEN_SESSION_CB cb) { - if (!CRYPTO_THREAD_write_lock(ctx->lock)) - return 0; - ctx->generate_session_id = cb; - CRYPTO_THREAD_unlock(ctx->lock); - return 1; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->generate_session_id = cb; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + return 1; + } + return 0; } int SSL_set_generate_session_id(SSL *ssl, GEN_SESSION_CB cb) @@ -1088,7 +1123,14 @@ int SSL_has_matching_session_id(const SSL *ssl, const unsigned char *id, int SSL_CTX_set_purpose(SSL_CTX *s, int purpose) { - return X509_VERIFY_PARAM_set_purpose(s->param, purpose); + int ret = 0; + + if (CRYPTO_THREAD_write_lock(s->cnf->cnf_lock)) { + ret = X509_VERIFY_PARAM_set_purpose(s->cnf->param, purpose); + CRYPTO_THREAD_unlock(s->cnf->cnf_lock); + } + + return ret; } int SSL_set_purpose(SSL *s, int purpose) @@ -1103,7 +1145,14 @@ int SSL_set_purpose(SSL *s, int purpose) int SSL_CTX_set_trust(SSL_CTX *s, int trust) { - return X509_VERIFY_PARAM_set_trust(s->param, trust); + int ret = 0; + + if (CRYPTO_THREAD_write_lock(s->cnf->cnf_lock)) { + ret = X509_VERIFY_PARAM_set_trust(s->cnf->param, trust); + CRYPTO_THREAD_unlock(s->cnf->cnf_lock); + } + + return ret; } int SSL_set_trust(SSL *s, int trust) @@ -1361,7 +1410,14 @@ int SSL_CTX_dane_mtype_set(SSL_CTX *ctx, const EVP_MD *md, uint8_t mtype, int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm) { - return X509_VERIFY_PARAM_set1(ctx->param, vpm); + int ret = 0; + + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = X509_VERIFY_PARAM_set1(ctx->cnf->param, vpm); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + + return ret; } int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm) @@ -1376,7 +1432,14 @@ int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm) X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx) { - return ctx->param; + X509_VERIFY_PARAM *ret = NULL; + + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ctx->cnf->param; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + + return ret; } X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl) @@ -1842,16 +1905,37 @@ int (*SSL_get_verify_callback(const SSL *s)) (int, X509_STORE_CTX *) { int SSL_CTX_get_verify_mode(const SSL_CTX *ctx) { - return ctx->verify_mode; + int ret = 0; + + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ctx->cnf->verify_mode; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + + return ret; } int SSL_CTX_get_verify_depth(const SSL_CTX *ctx) { - return X509_VERIFY_PARAM_get_depth(ctx->param); + int ret = 0; + + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = X509_VERIFY_PARAM_get_depth(ctx->cnf->param); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + + return ret; } int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx)) (int, X509_STORE_CTX *) { - return ctx->default_verify_callback; + DEFAULT_VERIFY_CALLBACK ret = NULL; + + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ctx->cnf->default_verify_callback; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + + return ret; } void SSL_set_verify(SSL *s, int mode, @@ -2046,16 +2130,27 @@ int SSL_copy_session_id(SSL *t, const SSL *f) /* Fix this so it checks all the valid key/cert options */ int SSL_CTX_check_private_key(const SSL_CTX *ctx) { - if ((ctx == NULL) || (ctx->cert->key->x509 == NULL)) { - ERR_raise(ERR_LIB_SSL, SSL_R_NO_CERTIFICATE_ASSIGNED); - return 0; - } - if (ctx->cert->key->privatekey == NULL) { - ERR_raise(ERR_LIB_SSL, SSL_R_NO_PRIVATE_KEY_ASSIGNED); - return 0; + int rv = 0; + + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + if ((ctx == NULL) || (ctx->cnf->cert->key->x509 == NULL)) { + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + ERR_raise(ERR_LIB_SSL, SSL_R_NO_CERTIFICATE_ASSIGNED); + goto end; + } + if (ctx->cnf->cert->key->privatekey == NULL) { + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + ERR_raise(ERR_LIB_SSL, SSL_R_NO_PRIVATE_KEY_ASSIGNED); + rv = 0; + goto end; + } + rv = X509_check_private_key + (ctx->cnf->cert->key->x509, ctx->cnf->cert->key->privatekey); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); } - return X509_check_private_key - (ctx->cert->key->x509, ctx->cert->key->privatekey); + +end: + return rv; } /* Fix this function so that it takes an optional type parameter */ @@ -2122,13 +2217,21 @@ int SSL_get_changed_async_fds(SSL *s, OSSL_ASYNC_FD *addfd, size_t *numaddfds, int SSL_CTX_set_async_callback(SSL_CTX *ctx, SSL_async_callback_fn callback) { - ctx->async_cb = callback; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->async_cb = callback; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return 1; } int SSL_CTX_set_async_callback_arg(SSL_CTX *ctx, void *arg) { - ctx->async_cb_arg = arg; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->async_cb_arg = arg; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return 1; } @@ -3086,39 +3189,70 @@ long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) switch (cmd) { case SSL_CTRL_GET_READ_AHEAD: - return ctx->read_ahead; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + l = ctx->cnf->read_ahead; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return l; case SSL_CTRL_SET_READ_AHEAD: - l = ctx->read_ahead; - ctx->read_ahead = larg; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + l = ctx->cnf->read_ahead; + ctx->cnf->read_ahead = larg; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } return l; case SSL_CTRL_SET_MSG_CALLBACK_ARG: - ctx->msg_callback_arg = parg; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->msg_callback_arg = parg; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } return 1; case SSL_CTRL_GET_MAX_CERT_LIST: - return (long)ctx->max_cert_list; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + l = (long)ctx->cnf->max_cert_list; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return l; case SSL_CTRL_SET_MAX_CERT_LIST: if (larg < 0) return 0; - l = (long)ctx->max_cert_list; - ctx->max_cert_list = (size_t)larg; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + l = (long)ctx->cnf->max_cert_list; + ctx->cnf->max_cert_list = (size_t)larg; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } return l; case SSL_CTRL_SET_SESS_CACHE_SIZE: if (larg < 0) return 0; - l = (long)ctx->session_cache_size; - ctx->session_cache_size = (size_t)larg; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + l = (long)ctx->cnf->session_cache_size; + ctx->cnf->session_cache_size = (size_t)larg; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } return l; case SSL_CTRL_GET_SESS_CACHE_SIZE: - return (long)ctx->session_cache_size; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + l = (long)ctx->cnf->session_cache_size; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return l; case SSL_CTRL_SET_SESS_CACHE_MODE: - l = ctx->session_cache_mode; - ctx->session_cache_mode = larg; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + l = ctx->cnf->session_cache_mode; + ctx->cnf->session_cache_mode = larg; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } return l; case SSL_CTRL_GET_SESS_CACHE_MODE: - return ctx->session_cache_mode; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + l = ctx->cnf->session_cache_mode; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return l; case SSL_CTRL_SESS_NUMBER: return lh_SSL_SESSION_num_items(ctx->sessions); @@ -3145,42 +3279,89 @@ long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) case SSL_CTRL_SESS_CACHE_FULL: return ssl_tsan_load(ctx, &ctx->stats.sess_cache_full); case SSL_CTRL_MODE: - return (ctx->mode |= larg); + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + l = (ctx->cnf->mode |= larg); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return l; case SSL_CTRL_CLEAR_MODE: - return (ctx->mode &= ~larg); + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + l = (ctx->cnf->mode &= ~larg); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return l; case SSL_CTRL_SET_MAX_SEND_FRAGMENT: if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH) return 0; - ctx->max_send_fragment = larg; - if (ctx->max_send_fragment < ctx->split_send_fragment) - ctx->split_send_fragment = ctx->max_send_fragment; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->max_send_fragment = larg; + if (ctx->cnf->max_send_fragment < ctx->cnf->split_send_fragment) + ctx->cnf->split_send_fragment = ctx->cnf->max_send_fragment; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } return 1; - case SSL_CTRL_SET_SPLIT_SEND_FRAGMENT: - if ((size_t)larg > ctx->max_send_fragment || larg == 0) - return 0; - ctx->split_send_fragment = larg; + case SSL_CTRL_SET_SPLIT_SEND_FRAGMENT: { + size_t max_send_fragment = 0; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + max_send_fragment = ctx->cnf->max_send_fragment; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + if ((size_t)larg > max_send_fragment || larg == 0) + return 0; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->split_send_fragment = larg; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + } return 1; case SSL_CTRL_SET_MAX_PIPELINES: if (larg < 1 || larg > SSL_MAX_PIPELINES) return 0; - ctx->max_pipelines = larg; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->max_pipelines = larg; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } return 1; case SSL_CTRL_CERT_FLAGS: - return (ctx->cert->cert_flags |= larg); + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + l = (ctx->cnf->cert->cert_flags |= larg); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return l; case SSL_CTRL_CLEAR_CERT_FLAGS: - return (ctx->cert->cert_flags &= ~larg); + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + l = (ctx->cnf->cert->cert_flags &= ~larg); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return l; case SSL_CTRL_SET_MIN_PROTO_VERSION: - return ssl_check_allowed_versions(larg, ctx->max_proto_version) - && ssl_set_version_bound(ctx->method->version, (int)larg, - &ctx->min_proto_version); + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + l = ssl_check_allowed_versions(larg, ctx->cnf->max_proto_version) + && ssl_set_version_bound(ctx->method->version, (int)larg, + &ctx->cnf->min_proto_version); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return l; case SSL_CTRL_GET_MIN_PROTO_VERSION: - return ctx->min_proto_version; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + l = ctx->cnf->min_proto_version; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return l; case SSL_CTRL_SET_MAX_PROTO_VERSION: - return ssl_check_allowed_versions(ctx->min_proto_version, larg) - && ssl_set_version_bound(ctx->method->version, (int)larg, - &ctx->max_proto_version); + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + l = ssl_check_allowed_versions(ctx->cnf->min_proto_version, larg) + && ssl_set_version_bound(ctx->method->version, (int)larg, + &ctx->cnf->max_proto_version); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return l; case SSL_CTRL_GET_MAX_PROTO_VERSION: - return ctx->max_proto_version; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + l = ctx->cnf->max_proto_version; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return l; default: return ctx->method->ssl_ctx_ctrl(ctx, cmd, larg, parg); } @@ -3190,10 +3371,13 @@ long SSL_CTX_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp) (void)) { switch (cmd) { case SSL_CTRL_SET_MSG_CALLBACK: - ctx->msg_callback = (void (*) - (int write_p, int version, int content_type, - const void *buf, size_t len, SSL *ssl, - void *arg))(fp); + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->msg_callback = (void (*) + (int write_p, int version, int content_type, + const void *buf, size_t len, SSL *ssl, + void *arg))(fp); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } return 1; default: @@ -3227,15 +3411,19 @@ int ssl_cipher_ptr_id_cmp(const SSL_CIPHER *const *ap, STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s) { const SSL_CONNECTION *sc = SSL_CONNECTION_FROM_CONST_SSL(s); + STACK_OF(SSL_CIPHER) * ret = NULL; if (sc != NULL) { if (sc->cipher_list != NULL) { - return sc->cipher_list; - } else if ((s->ctx != NULL) && (s->ctx->cipher_list != NULL)) { - return s->ctx->cipher_list; + ret = sc->cipher_list; + } else if (s->ctx != NULL) { + if (CRYPTO_THREAD_read_lock(s->ctx->cnf->cnf_lock)) { + ret = s->ctx->cnf->cipher_list; + CRYPTO_THREAD_unlock(s->ctx->cnf->cnf_lock); + } } } - return NULL; + return ret; } STACK_OF(SSL_CIPHER) *SSL_get_client_ciphers(const SSL *s) @@ -3281,14 +3469,18 @@ STACK_OF(SSL_CIPHER) *SSL_get1_supported_ciphers(SSL *s) * algorithm id */ STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL_CONNECTION *s) { + STACK_OF(SSL_CIPHER) *ret = NULL; if (s != NULL) { if (s->cipher_list_by_id != NULL) - return s->cipher_list_by_id; - else if (s->ssl.ctx != NULL - && s->ssl.ctx->cipher_list_by_id != NULL) - return s->ssl.ctx->cipher_list_by_id; + ret = s->cipher_list_by_id; + else if (s->ssl.ctx != NULL) { + if (CRYPTO_THREAD_read_lock(s->ssl.ctx->cnf->cnf_lock)) { + ret = s->ssl.ctx->cnf->cipher_list_by_id; + CRYPTO_THREAD_unlock(s->ssl.ctx->cnf->cnf_lock); + } + } } - return NULL; + return ret; } /** The old interface to get the same thing as SSL_get_ciphers() */ @@ -3312,9 +3504,14 @@ const char *SSL_get_cipher_list(const SSL *s, int n) * preference */ STACK_OF(SSL_CIPHER) *SSL_CTX_get_ciphers(const SSL_CTX *ctx) { - if (ctx != NULL) - return ctx->cipher_list; - return NULL; + STACK_OF(SSL_CIPHER) *ret = NULL; + if (ctx != NULL) { + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ctx->cnf->cipher_list; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + } + return ret; } /* @@ -3340,11 +3537,15 @@ static int cipher_list_tls12_num(STACK_OF(SSL_CIPHER) *sk) /** specify the ciphers to be used by default by the SSL_CTX */ int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) { - STACK_OF(SSL_CIPHER) *sk; + STACK_OF(SSL_CIPHER) *sk = NULL; + + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + sk = ssl_create_cipher_list(ctx, ctx->cnf->tls13_ciphersuites, + &ctx->cnf->cipher_list, &ctx->cnf->cipher_list_by_id, str, + ctx->cnf->cert); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } - sk = ssl_create_cipher_list(ctx, ctx->tls13_ciphersuites, - &ctx->cipher_list, &ctx->cipher_list_by_id, str, - ctx->cert); /* * ssl_create_cipher_list may return an empty stack if it was unable to * find a cipher matching the given rule string (for example if the rule @@ -3627,8 +3828,11 @@ void SSL_CTX_set_npn_advertised_cb(SSL_CTX *ctx, /* NPN not allowed for QUIC */ return; - ctx->ext.npn_advertised_cb = cb; - ctx->ext.npn_advertised_cb_arg = arg; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->ext.npn_advertised_cb = cb; + ctx->cnf->ext.npn_advertised_cb_arg = arg; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } /* @@ -3649,8 +3853,11 @@ void SSL_CTX_set_npn_select_cb(SSL_CTX *ctx, /* NPN not allowed for QUIC */ return; - ctx->ext.npn_select_cb = cb; - ctx->ext.npn_select_cb_arg = arg; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->ext.npn_select_cb = cb; + ctx->cnf->ext.npn_select_cb_arg = arg; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } #endif @@ -3678,9 +3885,12 @@ int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char *protos, unsigned char *alpn; if (protos_len == 0 || protos == NULL) { - OPENSSL_free(ctx->ext.alpn); - ctx->ext.alpn = NULL; - ctx->ext.alpn_len = 0; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + OPENSSL_free(ctx->cnf->ext.alpn); + ctx->cnf->ext.alpn = NULL; + ctx->cnf->ext.alpn_len = 0; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } return 0; } /* Not valid per RFC */ @@ -3690,9 +3900,13 @@ int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char *protos, alpn = OPENSSL_memdup(protos, protos_len); if (alpn == NULL) return 1; - OPENSSL_free(ctx->ext.alpn); - ctx->ext.alpn = alpn; - ctx->ext.alpn_len = protos_len; + + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + OPENSSL_free(ctx->cnf->ext.alpn); + ctx->cnf->ext.alpn = alpn; + ctx->cnf->ext.alpn_len = protos_len; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } return 0; } @@ -3740,8 +3954,11 @@ void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx, SSL_CTX_alpn_select_cb_func cb, void *arg) { - ctx->ext.alpn_select_cb = cb; - ctx->ext.alpn_select_cb_arg = arg; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->ext.alpn_select_cb = cb; + ctx->cnf->ext.alpn_select_cb_arg = arg; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } /* @@ -3841,6 +4058,35 @@ static int ssl_session_cmp(const SSL_SESSION *a, const SSL_SESSION *b) return memcmp(a->session_id, b->session_id, a->session_id_length); } +SSL_CTX *SSL_CTX_dup(OSSL_LIB_CTX *libctx, SSL_CTX *source, + const char *propq, const SSL_METHOD *meth) +{ + SSL_CTX *ret = NULL; + int ok = 0; + int i = 0; + int rv = 0; + + if (source == NULL) + goto exit; + + ret = SSL_CTX_new_ex(libctx, propq, meth); + if (ret) { + ret->cnf = source->cnf; + rv = CRYPTO_UP_REF(&source->cnf->references, &i); + if (rv <= 0) + goto exit; + + ok = 1; + } +exit: + if (ok == 0) { + if (ret != NULL) + SSL_CTX_free(ret); + ret = NULL; + } + return ret; +} + /* * These wrapper functions should remain rather than redeclaring * SSL_SESSION_hash and SSL_SESSION_cmp for void* types and casting each @@ -3852,6 +4098,8 @@ SSL_CTX *SSL_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq, const SSL_METHOD *meth) { SSL_CTX *ret = NULL; + SSL_CTX_CNF *cnf = NULL; + #ifndef OPENSSL_NO_COMP_ALG int i; #endif @@ -3880,6 +4128,18 @@ SSL_CTX *SSL_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq, return NULL; } + cnf = OPENSSL_zalloc(sizeof(*cnf)); + if (cnf == NULL) + return NULL; + + if (!CRYPTO_NEW_REF(&cnf->references, 1)) { + OPENSSL_free(ret); + return NULL; + } + + cnf->cnf_lock = CRYPTO_THREAD_lock_new(); + ret->cnf = cnf; + ret->lock = CRYPTO_THREAD_lock_new(); if (ret->lock == NULL) { ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB); @@ -3902,23 +4162,23 @@ SSL_CTX *SSL_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq, } ret->method = meth; - ret->min_proto_version = 0; - ret->max_proto_version = 0; - ret->mode = SSL_MODE_AUTO_RETRY; - ret->session_cache_mode = SSL_SESS_CACHE_SERVER; - ret->session_cache_size = SSL_SESSION_CACHE_MAX_SIZE_DEFAULT; + ret->cnf->min_proto_version = 0; + ret->cnf->max_proto_version = 0; + ret->cnf->mode = SSL_MODE_AUTO_RETRY; + ret->cnf->session_cache_mode = SSL_SESS_CACHE_SERVER; + ret->cnf->session_cache_size = SSL_SESSION_CACHE_MAX_SIZE_DEFAULT; /* We take the system default. */ - ret->session_timeout = meth->get_timeout(); - ret->max_cert_list = SSL_MAX_CERT_LIST_DEFAULT; - ret->verify_mode = SSL_VERIFY_NONE; + ret->cnf->session_timeout = meth->get_timeout(); + ret->cnf->max_cert_list = SSL_MAX_CERT_LIST_DEFAULT; + ret->cnf->verify_mode = SSL_VERIFY_NONE; ret->sessions = lh_SSL_SESSION_new(ssl_session_hash, ssl_session_cmp); if (ret->sessions == NULL) { ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB); goto err; } - ret->cert_store = X509_STORE_new(); - if (ret->cert_store == NULL) { + ret->cnf->cert_store = X509_STORE_new(); + if (ret->cnf->cert_store == NULL) { ERR_raise(ERR_LIB_SSL, ERR_R_X509_LIB); goto err; } @@ -3958,22 +4218,29 @@ SSL_CTX *SSL_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq, goto err; } - if ((ret->cert = ssl_cert_new(SSL_PKEY_NUM + ret->sigalg_list_len)) == NULL) { + if ((ret->cnf->cert = ssl_cert_new(SSL_PKEY_NUM + ret->sigalg_list_len)) == NULL) { ERR_raise(ERR_LIB_SSL, ERR_R_SSL_LIB); goto err; } - if (!ssl_create_cipher_list(ret, - ret->tls13_ciphersuites, - &ret->cipher_list, &ret->cipher_list_by_id, - OSSL_default_cipher_list(), ret->cert) - || sk_SSL_CIPHER_num(ret->cipher_list) <= 0) { - ERR_raise(ERR_LIB_SSL, SSL_R_LIBRARY_HAS_NO_CIPHERS); - goto err; + if (CRYPTO_THREAD_write_lock(ret->cnf->cnf_lock)) + { + int ciph_list_cnt = 0; + STACK_OF(SSL_CIPHER) *sk_cipher = ssl_create_cipher_list(ret, + ret->cnf->tls13_ciphersuites, + &ret->cnf->cipher_list, &ret->cnf->cipher_list_by_id, + OSSL_default_cipher_list(), ret->cnf->cert); + if (sk_cipher != NULL) + ciph_list_cnt = sk_SSL_CIPHER_num(ret->cnf->cipher_list); + CRYPTO_THREAD_unlock(ret->cnf->cnf_lock); + if (!sk_cipher || ciph_list_cnt <= 0) { + ERR_raise(ERR_LIB_SSL, SSL_R_LIBRARY_HAS_NO_CIPHERS); + goto err; + } } - ret->param = X509_VERIFY_PARAM_new(); - if (ret->param == NULL) { + ret->cnf->param = X509_VERIFY_PARAM_new(); + if (ret->cnf->param == NULL) { ERR_raise(ERR_LIB_SSL, ERR_R_X509_LIB); goto err; } @@ -3985,42 +4252,42 @@ SSL_CTX *SSL_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq, ret->md5 = ssl_evp_md_fetch(libctx, NID_md5, propq); ret->sha1 = ssl_evp_md_fetch(libctx, NID_sha1, propq); - if ((ret->ca_names = sk_X509_NAME_new_null()) == NULL) { + if ((ret->cnf->ca_names = sk_X509_NAME_new_null()) == NULL) { ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB); goto err; } - if ((ret->client_ca_names = sk_X509_NAME_new_null()) == NULL) { + if ((ret->cnf->client_ca_names = sk_X509_NAME_new_null()) == NULL) { ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB); goto err; } - if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_CTX, ret, &ret->ex_data)) { + if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_CTX, ret, &ret->cnf->ex_data)) { ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB); goto err; } - if ((ret->ext.secure = OPENSSL_secure_zalloc(sizeof(*ret->ext.secure))) == NULL) + if ((ret->cnf->ext.secure = OPENSSL_secure_zalloc(sizeof(*ret->cnf->ext.secure))) == NULL) goto err; /* No compression for DTLS */ if (!(meth->ssl3_enc->enc_flags & SSL_ENC_FLAG_DTLS)) ret->comp_methods = SSL_COMP_get_compression_methods(); - ret->max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH; - ret->split_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH; + ret->cnf->max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH; + ret->cnf->split_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH; /* Setup RFC5077 ticket keys */ - if ((RAND_bytes_ex(libctx, ret->ext.tick_key_name, - sizeof(ret->ext.tick_key_name), 0) <= 0) - || (RAND_priv_bytes_ex(libctx, ret->ext.secure->tick_hmac_key, - sizeof(ret->ext.secure->tick_hmac_key), 0) <= 0) - || (RAND_priv_bytes_ex(libctx, ret->ext.secure->tick_aes_key, - sizeof(ret->ext.secure->tick_aes_key), 0) <= 0)) - ret->options |= SSL_OP_NO_TICKET; - - if (RAND_priv_bytes_ex(libctx, ret->ext.cookie_hmac_key, - sizeof(ret->ext.cookie_hmac_key), 0) <= 0) { + if ((RAND_bytes_ex(libctx, ret->cnf->ext.tick_key_name, + sizeof(ret->cnf->ext.tick_key_name), 0) <= 0) + || (RAND_priv_bytes_ex(libctx, ret->cnf->ext.secure->tick_hmac_key, + sizeof(ret->cnf->ext.secure->tick_hmac_key), 0) <= 0) + || (RAND_priv_bytes_ex(libctx, ret->cnf->ext.secure->tick_aes_key, + sizeof(ret->cnf->ext.secure->tick_aes_key), 0) <= 0)) + ret->cnf->options |= SSL_OP_NO_TICKET; + + if (RAND_priv_bytes_ex(libctx, ret->cnf->ext.cookie_hmac_key, + sizeof(ret->cnf->ext.cookie_hmac_key), 0) <= 0) { ERR_raise(ERR_LIB_SSL, ERR_R_RAND_LIB); goto err; } @@ -4072,9 +4339,9 @@ SSL_CTX *SSL_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq, * middlebox compatibility by default. This may be disabled by default in * a later OpenSSL version. */ - ret->options |= SSL_OP_NO_COMPRESSION | SSL_OP_ENABLE_MIDDLEBOX_COMPAT; + ret->cnf->options |= SSL_OP_NO_COMPRESSION | SSL_OP_ENABLE_MIDDLEBOX_COMPAT; - ret->ext.status_type = TLSEXT_STATUSTYPE_nothing; + ret->cnf->ext.status_type = TLSEXT_STATUSTYPE_nothing; /* * We cannot usefully set a default max_early_data here (which gets @@ -4092,7 +4359,7 @@ SSL_CTX *SSL_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq, * eliminating the bandwidth-wasting early data in the case described * above. */ - ret->max_early_data = 0; + ret->cnf->max_early_data = 0; /* * Default recv_max_early_data is a fully loaded single record. Could be @@ -4102,10 +4369,10 @@ SSL_CTX *SSL_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq, * because of an old, stale ticket) then we will tolerate it and skip over * it. */ - ret->recv_max_early_data = SSL3_RT_MAX_PLAIN_LENGTH; + ret->cnf->recv_max_early_data = SSL3_RT_MAX_PLAIN_LENGTH; /* By default we send two session tickets automatically in TLSv1.3 */ - ret->num_tickets = 2; + ret->cnf->num_tickets = 2; ssl_ctx_system_config(ret); @@ -4122,19 +4389,49 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) int SSL_CTX_up_ref(SSL_CTX *ctx) { - int i; + int i, ii; if (CRYPTO_UP_REF(&ctx->references, &i) <= 0) return 0; + if (CRYPTO_UP_REF(&ctx->cnf->references, &ii) <= 0) + return 0; REF_PRINT_COUNT("SSL_CTX", ctx); REF_ASSERT_ISNT(i < 2); return ((i > 1) ? 1 : 0); } +void ssl_ctx_cnf_free(SSL_CTX *a, int refcount) +{ + if (refcount == 0) { + sk_SSL_CIPHER_free(a->cnf->cipher_list); + sk_SSL_CIPHER_free(a->cnf->cipher_list_by_id); + sk_SSL_CIPHER_free(a->cnf->tls13_ciphersuites); + ssl_cert_free(a->cnf->cert); + sk_X509_NAME_pop_free(a->cnf->ca_names, X509_NAME_free); + sk_X509_NAME_pop_free(a->cnf->client_ca_names, X509_NAME_free); + OSSL_STACK_OF_X509_free(a->cnf->extra_certs); +#ifndef OPENSSL_NO_ENGINE + tls_engine_finish(a->cnf->client_cert_engine); +#endif + X509_STORE_free(a->cnf->cert_store); + OPENSSL_free(a->cnf->ext.ecpointformats); + OPENSSL_free(a->cnf->ext.supportedgroups); + OPENSSL_free(a->cnf->ext.supported_groups_default); + OPENSSL_free(a->cnf->ext.alpn); + OPENSSL_secure_free(a->cnf->ext.secure); + X509_VERIFY_PARAM_free(a->cnf->param); + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_CTX, a, &a->cnf->ex_data); + CRYPTO_THREAD_lock_free(a->cnf->cnf_lock); + CRYPTO_FREE_REF(&a->cnf->references); + OPENSSL_free(a->cnf); + a->cnf = NULL; + } +} + void SSL_CTX_free(SSL_CTX *a) { - int i; + int i, ii; size_t j; if (a == NULL) @@ -4142,11 +4439,12 @@ void SSL_CTX_free(SSL_CTX *a) CRYPTO_DOWN_REF(&a->references, &i); REF_PRINT_COUNT("SSL_CTX", a); + CRYPTO_DOWN_REF(&a->cnf->references, &ii); + REF_PRINT_COUNT("SSL_CTX_CNF", a->cnf); + if (i > 0) return; REF_ASSERT_ISNT(i < 0); - - X509_VERIFY_PARAM_free(a->param); dane_ctx_final(&a->dane); /* @@ -4158,39 +4456,23 @@ void SSL_CTX_free(SSL_CTX *a) * free ex_data, then finally free the cache. * (See ticket [openssl.org #212].) */ + if (a->sessions != NULL) SSL_CTX_flush_sessions(a, 0); - CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_CTX, a, &a->ex_data); lh_SSL_SESSION_free(a->sessions); - X509_STORE_free(a->cert_store); + ssl_ctx_cnf_free(a, ii); #ifndef OPENSSL_NO_CT CTLOG_STORE_free(a->ctlog_store); #endif - sk_SSL_CIPHER_free(a->cipher_list); - sk_SSL_CIPHER_free(a->cipher_list_by_id); - sk_SSL_CIPHER_free(a->tls13_ciphersuites); - ssl_cert_free(a->cert); - sk_X509_NAME_pop_free(a->ca_names, X509_NAME_free); - sk_X509_NAME_pop_free(a->client_ca_names, X509_NAME_free); - OSSL_STACK_OF_X509_free(a->extra_certs); a->comp_methods = NULL; #ifndef OPENSSL_NO_SRTP sk_SRTP_PROTECTION_PROFILE_free(a->srtp_profiles); #endif + #ifndef OPENSSL_NO_SRP ssl_ctx_srp_ctx_free_intern(a); #endif -#ifndef OPENSSL_NO_ENGINE - tls_engine_finish(a->client_cert_engine); -#endif - - OPENSSL_free(a->ext.ecpointformats); - OPENSSL_free(a->ext.supportedgroups); - OPENSSL_free(a->ext.supported_groups_default); - OPENSSL_free(a->ext.alpn); - OPENSSL_secure_free(a->ext.secure); - ssl_evp_md_free(a->md5); ssl_evp_md_free(a->sha1); @@ -4237,22 +4519,42 @@ void SSL_CTX_free(SSL_CTX *a) void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb) { - ctx->default_passwd_callback = cb; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->default_passwd_callback = cb; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u) { - ctx->default_passwd_callback_userdata = u; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->default_passwd_callback_userdata = u; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } pem_password_cb *SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx) { - return ctx->default_passwd_callback; + pem_password_cb *ret = NULL; + + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ctx->cnf->default_passwd_callback; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + + return ret; } void *SSL_CTX_get_default_passwd_cb_userdata(SSL_CTX *ctx) { - return ctx->default_passwd_callback_userdata; + void *ret = NULL; + + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ctx->cnf->default_passwd_callback_userdata; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + + return ret; } void SSL_set_default_passwd_cb(SSL *s, pem_password_cb *cb) @@ -4299,25 +4601,37 @@ void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*cb) (X509_STORE_CTX *, void *), void *arg) { - ctx->app_verify_callback = cb; - ctx->app_verify_arg = arg; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->app_verify_callback = cb; + ctx->cnf->app_verify_arg = arg; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, int (*cb) (int, X509_STORE_CTX *)) { - ctx->verify_mode = mode; - ctx->default_verify_callback = cb; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->verify_mode = mode; + ctx->cnf->default_verify_callback = cb; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth) { - X509_VERIFY_PARAM_set_depth(ctx->param, depth); + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + X509_VERIFY_PARAM_set_depth(ctx->cnf->param, depth); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } void SSL_CTX_set_cert_cb(SSL_CTX *c, int (*cb) (SSL *ssl, void *arg), void *arg) { - ssl_cert_set_cert_cb(c->cert, cb, arg); + if (CRYPTO_THREAD_read_lock(c->cnf->cnf_lock)) { + ssl_cert_set_cert_cb(c->cnf->cert, cb, arg); + CRYPTO_THREAD_unlock(c->cnf->cnf_lock); + } } void SSL_set_cert_cb(SSL *s, int (*cb) (SSL *ssl, void *arg), void *arg) @@ -4481,7 +4795,7 @@ int ssl_get_server_cert_serverinfo(SSL_CONNECTION *s, void ssl_update_cache(SSL_CONNECTION *s, int mode) { - int i; + int i = 0; /* * If the session_id_length is 0, we are not supposed to cache it, and it @@ -4503,7 +4817,10 @@ void ssl_update_cache(SSL_CONNECTION *s, int mode) && (s->verify_mode & SSL_VERIFY_PEER) != 0) return; - i = s->session_ctx->session_cache_mode; + if (CRYPTO_THREAD_read_lock(s->session_ctx->cnf->cnf_lock)) { + i = s->session_ctx->cnf->session_cache_mode; + CRYPTO_THREAD_unlock(s->session_ctx->cnf->cnf_lock); + } if ((i & mode) != 0 && (!s->hit || SSL_CONNECTION_IS_TLS13(s))) { /* @@ -4517,25 +4834,28 @@ void ssl_update_cache(SSL_CONNECTION *s, int mode) * session timeout events * - SSL_OP_NO_TICKET is set in which case it is a stateful ticket */ - if ((i & SSL_SESS_CACHE_NO_INTERNAL_STORE) == 0 - && (!SSL_CONNECTION_IS_TLS13(s) - || !s->server - || (s->max_early_data > 0 - && (s->options & SSL_OP_NO_ANTI_REPLAY) == 0) - || s->session_ctx->remove_session_cb != NULL - || (s->options & SSL_OP_NO_TICKET) != 0)) - SSL_CTX_add_session(s->session_ctx, s->session); + if (CRYPTO_THREAD_read_lock(s->session_ctx->cnf->cnf_lock)) { + if ((i & SSL_SESS_CACHE_NO_INTERNAL_STORE) == 0 + && (!SSL_CONNECTION_IS_TLS13(s) + || !s->server + || (s->max_early_data > 0 + && (s->options & SSL_OP_NO_ANTI_REPLAY) == 0) + || s->session_ctx->cnf->remove_session_cb != NULL + || (s->options & SSL_OP_NO_TICKET) != 0)) + SSL_CTX_add_session(s->session_ctx, s->session); - /* + /* * Add the session to the external cache. We do this even in server side * TLSv1.3 without early data because some applications just want to * know about the creation of a session and aren't doing a full cache. */ - if (s->session_ctx->new_session_cb != NULL) { - SSL_SESSION_up_ref(s->session); - if (!s->session_ctx->new_session_cb(SSL_CONNECTION_GET_SSL(s), - s->session)) - SSL_SESSION_free(s->session); + if (s->session_ctx->cnf->new_session_cb != NULL) { + SSL_SESSION_up_ref(s->session); + if (!s->session_ctx->cnf->new_session_cb(SSL_CONNECTION_GET_SSL(s), + s->session)) + SSL_SESSION_free(s->session); + } + CRYPTO_THREAD_unlock(s->session_ctx->cnf->cnf_lock); } } @@ -5044,18 +5364,28 @@ EVP_PKEY *SSL_get_privatekey(const SSL *s) X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx) { - if (ctx->cert != NULL) - return ctx->cert->key->x509; - else - return NULL; + X509 *ret = NULL; + + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + if (ctx->cnf->cert != NULL) + ret = ctx->cnf->cert->key->x509; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + + return ret; } EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx) { - if (ctx->cert != NULL) - return ctx->cert->key->privatekey; - else - return NULL; + EVP_PKEY *ret = NULL; + + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + if (ctx->cnf->cert != NULL) + ret = ctx->cnf->cert->key->privatekey; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + + return ret; } const SSL_CIPHER *SSL_get_current_cipher(const SSL *s) @@ -5148,12 +5478,22 @@ int ssl_free_wbio_buffer(SSL_CONNECTION *s) void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx, int mode) { - ctx->quiet_shutdown = mode; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->quiet_shutdown = mode; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx) { - return ctx->quiet_shutdown; + int ret = 0; + + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ctx->cnf->quiet_shutdown; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + + return ret; } void SSL_set_quiet_shutdown(SSL *s, int mode) @@ -5242,7 +5582,7 @@ SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl) SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx) { - CERT *new_cert; + CERT *new_cert = NULL; SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL_ONLY(ssl); /* TODO(QUIC FUTURE): Add support for QUIC */ @@ -5253,7 +5593,12 @@ SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx) return ssl->ctx; if (ctx == NULL) ctx = sc->session_ctx; - new_cert = ssl_cert_dup(ctx->cert); + + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + new_cert = ssl_cert_dup(ctx->cnf->cert); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + if (new_cert == NULL) { return NULL; } @@ -5279,11 +5624,14 @@ SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx) * not match (i.e., it was set per-ssl with SSL_set_session_id_context), * leave it unchanged. */ - if ((ssl->ctx != NULL) && - (sc->sid_ctx_length == ssl->ctx->sid_ctx_length) && - (memcmp(sc->sid_ctx, ssl->ctx->sid_ctx, sc->sid_ctx_length) == 0)) { - sc->sid_ctx_length = ctx->sid_ctx_length; - memcpy(&sc->sid_ctx, &ctx->sid_ctx, sizeof(sc->sid_ctx)); + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + if ((ssl->ctx != NULL) && + (sc->sid_ctx_length == ssl->ctx->cnf->sid_ctx_length) && + (memcmp(sc->sid_ctx, ssl->ctx->cnf->sid_ctx, sc->sid_ctx_length) == 0)) { + sc->sid_ctx_length = ctx->cnf->sid_ctx_length; + memcpy(&sc->sid_ctx, &ctx->cnf->sid_ctx, sizeof(sc->sid_ctx)); + } + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); } SSL_CTX_up_ref(ctx); @@ -5295,15 +5643,24 @@ SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx) int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx) { - return X509_STORE_set_default_paths_ex(ctx->cert_store, ctx->libctx, - ctx->propq); + int ret = 0; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = X509_STORE_set_default_paths_ex(ctx->cnf->cert_store, ctx->libctx, + ctx->propq); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return ret; } int SSL_CTX_set_default_verify_dir(SSL_CTX *ctx) { - X509_LOOKUP *lookup; + X509_LOOKUP *lookup = NULL; + + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + lookup = X509_STORE_add_lookup(ctx->cnf->cert_store, X509_LOOKUP_hash_dir()); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } - lookup = X509_STORE_add_lookup(ctx->cert_store, X509_LOOKUP_hash_dir()); if (lookup == NULL) return 0; @@ -5319,9 +5676,13 @@ int SSL_CTX_set_default_verify_dir(SSL_CTX *ctx) int SSL_CTX_set_default_verify_file(SSL_CTX *ctx) { - X509_LOOKUP *lookup; + X509_LOOKUP *lookup = NULL; + + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + lookup = X509_STORE_add_lookup(ctx->cnf->cert_store, X509_LOOKUP_file()); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } - lookup = X509_STORE_add_lookup(ctx->cert_store, X509_LOOKUP_file()); if (lookup == NULL) return 0; @@ -5338,9 +5699,13 @@ int SSL_CTX_set_default_verify_file(SSL_CTX *ctx) int SSL_CTX_set_default_verify_store(SSL_CTX *ctx) { - X509_LOOKUP *lookup; + X509_LOOKUP *lookup = NULL; + + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + lookup = X509_STORE_add_lookup(ctx->cnf->cert_store, X509_LOOKUP_store()); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } - lookup = X509_STORE_add_lookup(ctx->cert_store, X509_LOOKUP_store()); if (lookup == NULL) return 0; @@ -5356,19 +5721,34 @@ int SSL_CTX_set_default_verify_store(SSL_CTX *ctx) int SSL_CTX_load_verify_file(SSL_CTX *ctx, const char *CAfile) { - return X509_STORE_load_file_ex(ctx->cert_store, CAfile, ctx->libctx, - ctx->propq); + int ret = 0; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = X509_STORE_load_file_ex(ctx->cnf->cert_store, CAfile, ctx->libctx, + ctx->propq); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return ret; } int SSL_CTX_load_verify_dir(SSL_CTX *ctx, const char *CApath) { - return X509_STORE_load_path(ctx->cert_store, CApath); + int ret = 0; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = X509_STORE_load_path(ctx->cnf->cert_store, CApath); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return ret; } int SSL_CTX_load_verify_store(SSL_CTX *ctx, const char *CAstore) { - return X509_STORE_load_store_ex(ctx->cert_store, CAstore, ctx->libctx, - ctx->propq); + int ret = 0; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = X509_STORE_load_store_ex(ctx->cnf->cert_store, CAstore, ctx->libctx, + ctx->propq); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return ret; } int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, @@ -5494,23 +5874,45 @@ void *SSL_get_ex_data(const SSL *s, int idx) int SSL_CTX_set_ex_data(SSL_CTX *s, int idx, void *arg) { - return CRYPTO_set_ex_data(&s->ex_data, idx, arg); + int ret = 0; + + if (CRYPTO_THREAD_write_lock(s->cnf->cnf_lock)) { + ret = CRYPTO_set_ex_data(&s->cnf->ex_data, idx, arg); + CRYPTO_THREAD_unlock(s->cnf->cnf_lock); + } + + return ret; } void *SSL_CTX_get_ex_data(const SSL_CTX *s, int idx) { - return CRYPTO_get_ex_data(&s->ex_data, idx); + void *ret = NULL; + + if (CRYPTO_THREAD_write_lock(s->cnf->cnf_lock)) { + ret = CRYPTO_get_ex_data(&s->cnf->ex_data, idx); + CRYPTO_THREAD_unlock(s->cnf->cnf_lock); + } + + return ret; } X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *ctx) { - return ctx->cert_store; + X509_STORE *ret = NULL; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ctx->cnf->cert_store; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return ret; } void SSL_CTX_set_cert_store(SSL_CTX *ctx, X509_STORE *store) { - X509_STORE_free(ctx->cert_store); - ctx->cert_store = store; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + X509_STORE_free(ctx->cnf->cert_store); + ctx->cnf->cert_store = store; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } void SSL_CTX_set1_cert_store(SSL_CTX *ctx, X509_STORE *store) @@ -5538,18 +5940,24 @@ int SSL_want(const SSL *s) #ifndef OPENSSL_NO_PSK int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint) { + int ret = 0; if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) { ERR_raise(ERR_LIB_SSL, SSL_R_DATA_LENGTH_TOO_LONG); return 0; } - OPENSSL_free(ctx->cert->psk_identity_hint); - if (identity_hint != NULL) { - ctx->cert->psk_identity_hint = OPENSSL_strdup(identity_hint); - if (ctx->cert->psk_identity_hint == NULL) - return 0; - } else - ctx->cert->psk_identity_hint = NULL; - return 1; + OPENSSL_free(ctx->cnf->cert->psk_identity_hint); + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + if (identity_hint != NULL) { + ctx->cnf->cert->psk_identity_hint = OPENSSL_strdup(identity_hint); + if (ctx->cnf->cert->psk_identity_hint == NULL) + ret = 0; + } else + ctx->cnf->cert->psk_identity_hint = NULL; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + + ret = 1; + return ret; } int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint) @@ -5605,7 +6013,10 @@ void SSL_set_psk_client_callback(SSL *s, SSL_psk_client_cb_func cb) void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx, SSL_psk_client_cb_func cb) { - ctx->psk_client_callback = cb; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->psk_client_callback = cb; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } void SSL_set_psk_server_callback(SSL *s, SSL_psk_server_cb_func cb) @@ -5620,7 +6031,10 @@ void SSL_set_psk_server_callback(SSL *s, SSL_psk_server_cb_func cb) void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx, SSL_psk_server_cb_func cb) { - ctx->psk_server_callback = cb; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->psk_server_callback = cb; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } #endif @@ -5637,7 +6051,10 @@ void SSL_set_psk_find_session_callback(SSL *s, SSL_psk_find_session_cb_func cb) void SSL_CTX_set_psk_find_session_callback(SSL_CTX *ctx, SSL_psk_find_session_cb_func cb) { - ctx->psk_find_session_cb = cb; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->psk_find_session_cb = cb; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } void SSL_set_psk_use_session_callback(SSL *s, SSL_psk_use_session_cb_func cb) @@ -5653,7 +6070,10 @@ void SSL_set_psk_use_session_callback(SSL *s, SSL_psk_use_session_cb_func cb) void SSL_CTX_set_psk_use_session_callback(SSL_CTX *ctx, SSL_psk_use_session_cb_func cb) { - ctx->psk_use_session_cb = cb; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->psk_use_session_cb = cb; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } void SSL_CTX_set_msg_callback(SSL_CTX *ctx, @@ -5693,32 +6113,50 @@ void SSL_CTX_set_record_padding_callback(SSL_CTX *ctx, size_t (*cb) (SSL *ssl, int type, size_t len, void *arg)) { - ctx->record_padding_cb = cb; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->record_padding_cb = cb; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } void SSL_CTX_set_record_padding_callback_arg(SSL_CTX *ctx, void *arg) { - ctx->record_padding_arg = arg; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->record_padding_arg = arg; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } void *SSL_CTX_get_record_padding_callback_arg(const SSL_CTX *ctx) { - return ctx->record_padding_arg; + void *ret = NULL; + + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ctx->cnf->record_padding_arg; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + + return ret; } int SSL_CTX_set_block_padding(SSL_CTX *ctx, size_t block_size) { + int ret = 1; + if (IS_QUIC_CTX(ctx) && block_size > 1) return 0; /* block size of 0 or 1 is basically no padding */ - if (block_size == 1) - ctx->block_padding = 0; - else if (block_size <= SSL3_RT_MAX_PLAIN_LENGTH) - ctx->block_padding = block_size; - else - return 0; - return 1; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + if (block_size == 1) + ctx->cnf->block_padding = 0; + else if (block_size <= SSL3_RT_MAX_PLAIN_LENGTH) + ctx->cnf->block_padding = block_size; + else + ret = 0; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return ret; } int SSL_set_record_padding_callback(SSL *ssl, @@ -5800,14 +6238,23 @@ size_t SSL_get_num_tickets(const SSL *s) int SSL_CTX_set_num_tickets(SSL_CTX *ctx, size_t num_tickets) { - ctx->num_tickets = num_tickets; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->num_tickets = num_tickets; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } return 1; } size_t SSL_CTX_get_num_tickets(const SSL_CTX *ctx) { - return ctx->num_tickets; + size_t ret = 0; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ctx->cnf->num_tickets; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + + return ret; } /* Retrieve handshake hashes */ @@ -5941,12 +6388,20 @@ void *SSL_get0_security_ex_data(const SSL *s) void SSL_CTX_set_security_level(SSL_CTX *ctx, int level) { - ctx->cert->sec_level = level; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->cert->sec_level = level; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } int SSL_CTX_get_security_level(const SSL_CTX *ctx) { - return ctx->cert->sec_level; + int ret = 0; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ctx->cnf->cert->sec_level; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return ret; } void SSL_CTX_set_security_callback(SSL_CTX *ctx, @@ -5954,7 +6409,10 @@ void SSL_CTX_set_security_callback(SSL_CTX *ctx, int op, int bits, int nid, void *other, void *ex)) { - ctx->cert->sec_cb = cb; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->cert->sec_cb = cb; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } int (*SSL_CTX_get_security_callback(const SSL_CTX *ctx)) (const SSL *s, @@ -5963,22 +6421,43 @@ int (*SSL_CTX_get_security_callback(const SSL_CTX *ctx)) (const SSL *s, int nid, void *other, void *ex) { - return ctx->cert->sec_cb; + int (*ret) (const SSL *s, const SSL_CTX *ctx, int op, int bits, int nid, + void *other, void *ex); + ret = NULL; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ctx->cnf->cert->sec_cb; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return ret; } void SSL_CTX_set0_security_ex_data(SSL_CTX *ctx, void *ex) { - ctx->cert->sec_ex = ex; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->cert->sec_ex = ex; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } void *SSL_CTX_get0_security_ex_data(const SSL_CTX *ctx) { - return ctx->cert->sec_ex; + void *ret = NULL; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ctx->cnf->cert->sec_ex; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + + return ret; } uint64_t SSL_CTX_get_options(const SSL_CTX *ctx) { - return ctx->options; + uint64_t ret = 0; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ctx->cnf->options; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return ret; } uint64_t SSL_get_options(const SSL *s) @@ -5998,7 +6477,12 @@ uint64_t SSL_get_options(const SSL *s) uint64_t SSL_CTX_set_options(SSL_CTX *ctx, uint64_t op) { - return ctx->options |= op; + uint64_t ret = 0; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ret = ctx->cnf->options |= op; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return ret; } uint64_t SSL_set_options(SSL *s, uint64_t op) @@ -6030,7 +6514,12 @@ uint64_t SSL_set_options(SSL *s, uint64_t op) uint64_t SSL_CTX_clear_options(SSL_CTX *ctx, uint64_t op) { - return ctx->options &= ~op; + uint64_t ret = 0; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ret = ctx->cnf->options &= ~op; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return ret; } uint64_t SSL_clear_options(SSL *s, uint64_t op) @@ -6303,8 +6792,11 @@ int SSL_CTX_set_ct_validation_callback(SSL_CTX *ctx, return 0; } - ctx->ct_validation_callback = callback; - ctx->ct_validation_callback_arg = arg; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->ct_validation_callback = callback; + ctx->cnf->ct_validation_callback_arg = arg; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } return 1; } @@ -6320,7 +6812,12 @@ int SSL_ct_is_enabled(const SSL *s) int SSL_CTX_ct_is_enabled(const SSL_CTX *ctx) { - return ctx->ct_validation_callback != NULL; + int ret = 0; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ctx->cnf->ct_validation_callback != NULL; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return ret; } int ssl_validate_ct(SSL_CONNECTION *s) @@ -6476,8 +6973,11 @@ const CTLOG_STORE *SSL_CTX_get0_ctlog_store(const SSL_CTX *ctx) void SSL_CTX_set_client_hello_cb(SSL_CTX *c, SSL_client_hello_cb_fn cb, void *arg) { - c->client_hello_cb = cb; - c->client_hello_cb_arg = arg; + if (CRYPTO_THREAD_write_lock(c->cnf->cnf_lock)) { + c->cnf->client_hello_cb = cb; + c->cnf->client_hello_cb_arg = arg; + CRYPTO_THREAD_unlock(c->cnf->cnf_lock); + } } int SSL_client_hello_isv2(SSL *s) @@ -6697,12 +7197,20 @@ int SSL_alloc_buffers(SSL *ssl) void SSL_CTX_set_keylog_callback(SSL_CTX *ctx, SSL_CTX_keylog_cb_func cb) { - ctx->keylog_callback = cb; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->keylog_callback = cb; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } SSL_CTX_keylog_cb_func SSL_CTX_get_keylog_callback(const SSL_CTX *ctx) { - return ctx->keylog_callback; + SSL_CTX_keylog_cb_func ret = NULL; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ctx->cnf->keylog_callback; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return ret; } static int nss_keylog_int(const char *prefix, @@ -6718,8 +7226,14 @@ static int nss_keylog_int(const char *prefix, size_t i; size_t prefix_len; SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(sc); + int rv = 0; - if (sctx->keylog_callback == NULL) + if (CRYPTO_THREAD_read_lock(sctx->cnf->cnf_lock)) { + if (sctx->cnf->keylog_callback == NULL) + rv = 1; + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + } + if (rv) return 1; /* @@ -6751,7 +7265,10 @@ static int nss_keylog_int(const char *prefix, } *cursor = '\0'; - sctx->keylog_callback(SSL_CONNECTION_GET_SSL(sc), (const char *)out); + if (CRYPTO_THREAD_read_lock(sctx->cnf->cnf_lock)) { + sctx->cnf->keylog_callback(SSL_CONNECTION_GET_SSL(sc), (const char *)out); + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + } OPENSSL_clear_free(out, out_len); return 1; @@ -6960,14 +7477,23 @@ int ossl_bytes_to_cipher_list(SSL_CONNECTION *s, PACKET *cipher_suites, int SSL_CTX_set_max_early_data(SSL_CTX *ctx, uint32_t max_early_data) { - ctx->max_early_data = max_early_data; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->max_early_data = max_early_data; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } return 1; } uint32_t SSL_CTX_get_max_early_data(const SSL_CTX *ctx) { - return ctx->max_early_data; + uint32_t ret = 0; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ctx->cnf->max_early_data; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + + return ret; } int SSL_set_max_early_data(SSL *s, uint32_t max_early_data) @@ -6994,14 +7520,23 @@ uint32_t SSL_get_max_early_data(const SSL *s) int SSL_CTX_set_recv_max_early_data(SSL_CTX *ctx, uint32_t recv_max_early_data) { - ctx->recv_max_early_data = recv_max_early_data; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->recv_max_early_data = recv_max_early_data; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } return 1; } uint32_t SSL_CTX_get_recv_max_early_data(const SSL_CTX *ctx) { - return ctx->recv_max_early_data; + uint32_t ret = 0; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ctx->cnf->recv_max_early_data; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + + return ret; } int SSL_set_recv_max_early_data(SSL *s, uint32_t recv_max_early_data) @@ -7080,7 +7615,10 @@ int SSL_stateless(SSL *s) void SSL_CTX_set_post_handshake_auth(SSL_CTX *ctx, int val) { - ctx->pha_enabled = val; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->pha_enabled = val; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } void SSL_set_post_handshake_auth(SSL *ssl, int val) @@ -7157,9 +7695,12 @@ int SSL_CTX_set_session_ticket_cb(SSL_CTX *ctx, SSL_CTX_decrypt_session_ticket_fn dec_cb, void *arg) { - ctx->generate_ticket_cb = gen_cb; - ctx->decrypt_ticket_cb = dec_cb; - ctx->ticket_cb_data = arg; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->generate_ticket_cb = gen_cb; + ctx->cnf->decrypt_ticket_cb = dec_cb; + ctx->cnf->ticket_cb_data = arg; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } return 1; } @@ -7167,8 +7708,11 @@ void SSL_CTX_set_allow_early_data_cb(SSL_CTX *ctx, SSL_allow_early_data_cb_fn cb, void *arg) { - ctx->allow_early_data_cb = cb; - ctx->allow_early_data_cb_data = arg; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->allow_early_data_cb = cb; + ctx->cnf->allow_early_data_cb_data = arg; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } void SSL_set_allow_early_data_cb(SSL *s, @@ -7300,8 +7844,11 @@ int SSL_CTX_set0_tmp_dh_pkey(SSL_CTX *ctx, EVP_PKEY *dhpkey) ERR_raise(ERR_LIB_SSL, SSL_R_DH_KEY_TOO_SMALL); return 0; } - EVP_PKEY_free(ctx->cert->dh_tmp); - ctx->cert->dh_tmp = dhpkey; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + EVP_PKEY_free(ctx->cnf->cert->dh_tmp); + ctx->cnf->cert->dh_tmp = dhpkey; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } return 1; } diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h index 4e99ada22cdf24..8ad03ae1e8fc44 100644 --- a/ssl/ssl_local.h +++ b/ssl/ssl_local.h @@ -804,36 +804,69 @@ typedef struct { # define TLS_GROUP_FFDHE_FOR_TLS1_3 (TLS_GROUP_FFDHE|TLS_GROUP_ONLY_FOR_TLS1_3) -struct ssl_ctx_st { - OSSL_LIB_CTX *libctx; +typedef int (*CLIENT_CERT_CB) (SSL *ssl, X509 **x509, EVP_PKEY **pkey); +typedef int (*APP_GEN_COOKIE_CB) (SSL *ssl, unsigned char *cookie, + unsigned int *cookie_len); +typedef int (*APP_VERIFY_COOKIE_CB) (SSL *ssl, const unsigned char *cookie, + unsigned int cookie_len); +typedef int (*GEN_STATELESS_COOKIE_CB) (SSL *ssl, unsigned char *cookie, + size_t *cookie_len); +typedef int (*VERIFY_STATELESS_COOKIE_CB) (SSL *ssl, const unsigned char *cookie, + size_t cookie_len); +typedef int (*DEFAULT_VERIFY_CALLBACK) (int ok, X509_STORE_CTX *ctx); + +typedef void (*INFO_CALLBACK) (const SSL *ssl, int type, int val); + +typedef SSL_SESSION *(*GET_SESSION_CB) (struct ssl_st *ssl, + const unsigned char *data, int len, + int *copy); + +typedef int (*NEW_SESSION_CB) (struct ssl_st *ssl, SSL_SESSION *sess); +typedef void (*REMOVE_SESSION_CB) (struct ssl_ctx_st *ctx, SSL_SESSION *sess); +# ifndef OPENSSL_NO_DEPRECATED_3_0 + /* Callback to support customisation of ticket key setting */ +typedef int (*TICKET_KEY_CB) (SSL *ssl, + unsigned char *name, unsigned char *iv, + EVP_CIPHER_CTX *ectx, HMAC_CTX *hctx, int enc); +#endif +typedef int (*TICKET_KEY_EVP_CB) (SSL *ssl, + unsigned char *name, unsigned char *iv, + EVP_CIPHER_CTX *ectx, EVP_MAC_CTX *hctx, + int enc); - const SSL_METHOD *method; +typedef struct ssl_ctx_cnf_st { + CRYPTO_RWLOCK *cnf_lock; + CRYPTO_REF_COUNT references; STACK_OF(SSL_CIPHER) *cipher_list; + /* same as above but sorted for lookup */ STACK_OF(SSL_CIPHER) *cipher_list_by_id; + /* TLSv1.3 specific ciphersuites */ STACK_OF(SSL_CIPHER) *tls13_ciphersuites; + struct x509_store_st /* X509_STORE */ *cert_store; - LHASH_OF(SSL_SESSION) *sessions; + /* * Most session-ids that will be cached, default is * SSL_SESSION_CACHE_MAX_SIZE_DEFAULT. 0 is unlimited. */ size_t session_cache_size; - struct ssl_session_st *session_cache_head; - struct ssl_session_st *session_cache_tail; - /* - * This can have one of 2 values, ored together, SSL_SESS_CACHE_CLIENT, - * SSL_SESS_CACHE_SERVER, Default is SSL_SESSION_CACHE_SERVER, which - * means only SSL_accept will cache SSL_SESSIONS. - */ - uint32_t session_cache_mode; + /* * If timeout is not 0, it is the default timeout value set when * SSL_new() is called. This has been put in to make life easier to set * things up */ OSSL_TIME session_timeout; + + /* + * This can have one of 2 values, ored together, SSL_SESS_CACHE_CLIENT, + * SSL_SESS_CACHE_SERVER, Default is SSL_SESSION_CACHE_SERVER, which + * means only SSL_accept will cache SSL_SESSIONS. + */ + uint32_t session_cache_mode; + /* * If this callback is not null, it will be called each time a session id * is added to the cache. If this function returns 1, it means that the @@ -843,44 +876,18 @@ struct ssl_ctx_st { * removed from the cache. After the call, OpenSSL will * SSL_SESSION_free() it. */ - int (*new_session_cb) (struct ssl_st *ssl, SSL_SESSION *sess); - void (*remove_session_cb) (struct ssl_ctx_st *ctx, SSL_SESSION *sess); - SSL_SESSION *(*get_session_cb) (struct ssl_st *ssl, - const unsigned char *data, int len, - int *copy); - struct { - TSAN_QUALIFIER int sess_connect; /* SSL new conn - started */ - TSAN_QUALIFIER int sess_connect_renegotiate; /* SSL reneg - requested */ - TSAN_QUALIFIER int sess_connect_good; /* SSL new conne/reneg - finished */ - TSAN_QUALIFIER int sess_accept; /* SSL new accept - started */ - TSAN_QUALIFIER int sess_accept_renegotiate; /* SSL reneg - requested */ - TSAN_QUALIFIER int sess_accept_good; /* SSL accept/reneg - finished */ - TSAN_QUALIFIER int sess_miss; /* session lookup misses */ - TSAN_QUALIFIER int sess_timeout; /* reuse attempt on timeouted session */ - TSAN_QUALIFIER int sess_cache_full; /* session removed due to full cache */ - TSAN_QUALIFIER int sess_hit; /* session reuse actually done */ - TSAN_QUALIFIER int sess_cb_hit; /* session-id that was not in - * the cache was passed back via - * the callback. This indicates - * that the application is - * supplying session-id's from - * other processes - spooky - * :-) */ - } stats; -#ifdef TSAN_REQUIRES_LOCKING - CRYPTO_RWLOCK *tsan_lock; -#endif - - CRYPTO_REF_COUNT references; + NEW_SESSION_CB new_session_cb; + REMOVE_SESSION_CB remove_session_cb; + GET_SESSION_CB get_session_cb; /* if defined, these override the X509_verify_cert() calls */ int (*app_verify_callback) (X509_STORE_CTX *, void *); void *app_verify_arg; + /* * before OpenSSL 0.9.7, 'app_verify_arg' was ignored * ('app_verify_callback' was called with just one argument) */ - /* Default password callback. */ pem_password_cb *default_passwd_callback; @@ -888,36 +895,28 @@ struct ssl_ctx_st { void *default_passwd_callback_userdata; /* get client cert callback */ - int (*client_cert_cb) (SSL *ssl, X509 **x509, EVP_PKEY **pkey); + CLIENT_CERT_CB client_cert_cb; /* cookie generate callback */ - int (*app_gen_cookie_cb) (SSL *ssl, unsigned char *cookie, - unsigned int *cookie_len); + APP_GEN_COOKIE_CB app_gen_cookie_cb; /* verify cookie callback */ - int (*app_verify_cookie_cb) (SSL *ssl, const unsigned char *cookie, - unsigned int cookie_len); + APP_VERIFY_COOKIE_CB app_verify_cookie_cb; /* TLS1.3 app-controlled cookie generate callback */ - int (*gen_stateless_cookie_cb) (SSL *ssl, unsigned char *cookie, - size_t *cookie_len); + GEN_STATELESS_COOKIE_CB gen_stateless_cookie_cb; /* TLS1.3 verify app-controlled cookie callback */ - int (*verify_stateless_cookie_cb) (SSL *ssl, const unsigned char *cookie, - size_t cookie_len); + VERIFY_STATELESS_COOKIE_CB verify_stateless_cookie_cb; CRYPTO_EX_DATA ex_data; - const EVP_MD *md5; /* For SSLv3/TLSv1 'ssl3-md5' */ - const EVP_MD *sha1; /* For SSLv3/TLSv1 'ssl3-sha1' */ - STACK_OF(X509) *extra_certs; - STACK_OF(SSL_COMP) *comp_methods; /* stack of SSL_COMP, SSLv3/TLSv1 */ /* Default values used when no per-SSL value is defined follow */ /* used if SSL's info_callback is NULL */ - void (*info_callback) (const SSL *ssl, int type, int val); + INFO_CALLBACK info_callback; /* * What we put in certificate_authorities extension for TLS 1.3 @@ -940,7 +939,7 @@ struct ssl_ctx_st { size_t max_cert_list; struct cert_st /* CERT */ *cert; - SSL_CERT_LOOKUP *ssl_cert_info; + int read_ahead; /* callback that allows applications to peek at protocol messages */ @@ -951,7 +950,7 @@ struct ssl_ctx_st { size_t sid_ctx_length; unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH]; /* called 'verify_callback' in the SSL */ - int (*default_verify_callback) (int ok, X509_STORE_CTX *ctx); + DEFAULT_VERIFY_CALLBACK default_verify_callback; /* Default generate session ID callback. */ GEN_SESSION_CB generate_session_id; @@ -961,7 +960,6 @@ struct ssl_ctx_st { int quiet_shutdown; # ifndef OPENSSL_NO_CT - CTLOG_STORE *ctlog_store; /* CT Log Store */ /* * Validates that the SCTs (Signed Certificate Timestamps) are sufficient. * If they are not, the connection should be aborted. @@ -970,6 +968,7 @@ struct ssl_ctx_st { void *ct_validation_callback_arg; # endif + /* * If we're using more than one pipeline how should we divide the data * up between the pipes? @@ -1091,25 +1090,12 @@ struct ssl_ctx_st { SSL_psk_find_session_cb_func psk_find_session_cb; SSL_psk_use_session_cb_func psk_use_session_cb; -# ifndef OPENSSL_NO_SRP - SRP_CTX srp_ctx; /* ctx for SRP authentication */ -# endif - - /* Shared DANE context */ - struct dane_ctx_st dane; - -# ifndef OPENSSL_NO_SRTP - /* SRTP profiles we are willing to do from RFC 5764 */ - STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles; -# endif /* * Callback for disabling session caching and ticket support on a session * basis, depending on the chosen cipher. */ int (*not_resumable_session_cb) (SSL *ssl, int is_forward_secure); - CRYPTO_RWLOCK *lock; - /* * Callback for logging key material for use with debugging tools like * Wireshark. The callback should log `line` followed by a newline. @@ -1152,6 +1138,65 @@ struct ssl_ctx_st { SSL_async_callback_fn async_cb; void *async_cb_arg; +}SSL_CTX_CNF; + +struct ssl_ctx_st { + OSSL_LIB_CTX *libctx; + SSL_CTX_CNF *cnf; + const SSL_METHOD *method; + + LHASH_OF(SSL_SESSION) *sessions; + struct ssl_session_st *session_cache_head; + struct ssl_session_st *session_cache_tail; + struct { + TSAN_QUALIFIER int sess_connect; /* SSL new conn - started */ + TSAN_QUALIFIER int sess_connect_renegotiate; /* SSL reneg - requested */ + TSAN_QUALIFIER int sess_connect_good; /* SSL new conne/reneg - finished */ + TSAN_QUALIFIER int sess_accept; /* SSL new accept - started */ + TSAN_QUALIFIER int sess_accept_renegotiate; /* SSL reneg - requested */ + TSAN_QUALIFIER int sess_accept_good; /* SSL accept/reneg - finished */ + TSAN_QUALIFIER int sess_miss; /* session lookup misses */ + TSAN_QUALIFIER int sess_timeout; /* reuse attempt on timeouted session */ + TSAN_QUALIFIER int sess_cache_full; /* session removed due to full cache */ + TSAN_QUALIFIER int sess_hit; /* session reuse actually done */ + TSAN_QUALIFIER int sess_cb_hit; /* session-id that was not in + * the cache was passed back via + * the callback. This indicates + * that the application is + * supplying session-id's from + * other processes - spooky + * :-) */ + } stats; +#ifdef TSAN_REQUIRES_LOCKING + CRYPTO_RWLOCK *tsan_lock; +#endif + + CRYPTO_REF_COUNT references; + + const EVP_MD *md5; /* For SSLv3/TLSv1 'ssl3-md5' */ + const EVP_MD *sha1; /* For SSLv3/TLSv1 'ssl3-sha1' */ + SSL_CERT_LOOKUP *ssl_cert_info; + + STACK_OF(SSL_COMP) *comp_methods; /* stack of SSL_COMP, SSLv3/TLSv1 */ + +# ifndef OPENSSL_NO_CT + CTLOG_STORE *ctlog_store; /* CT Log Store */ +# endif + +# ifndef OPENSSL_NO_SRP + SRP_CTX srp_ctx; /* ctx for SRP authentication */ +# endif + + /* Shared DANE context */ + struct dane_ctx_st dane; + +# ifndef OPENSSL_NO_SRTP + /* SRTP profiles we are willing to do from RFC 5764 */ + STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles; +# endif + + CRYPTO_RWLOCK *lock; + char *propq; int ssl_mac_pkey_id[SSL_MD_NUM_IDX]; diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c index c245c24080f36a..df24546c1e5319 100644 --- a/ssl/ssl_rsa.c +++ b/ssl/ssl_rsa.c @@ -228,7 +228,7 @@ int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const unsigned char *d, int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) { - int rv; + int rv = 0; if (x == NULL) { ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER); return 0; @@ -239,7 +239,12 @@ int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) ERR_raise(ERR_LIB_SSL, rv); return 0; } - return ssl_set_cert(ctx->cert, x, ctx); + + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + rv = ssl_set_cert(ctx->cnf->cert, x, ctx); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return rv; } static int ssl_set_cert(CERT *c, X509 *x, SSL_CTX *ctx) @@ -321,8 +326,11 @@ int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type) cert = d2i_X509_bio(in, &x); } else if (type == SSL_FILETYPE_PEM) { j = ERR_R_PEM_LIB; - cert = PEM_read_bio_X509(in, &x, ctx->default_passwd_callback, - ctx->default_passwd_callback_userdata); + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + cert = PEM_read_bio_X509(in, &x, ctx->cnf->default_passwd_callback, + ctx->cnf->default_passwd_callback_userdata); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } else { ERR_raise(ERR_LIB_SSL, SSL_R_BAD_SSL_FILETYPE); goto end; @@ -363,11 +371,16 @@ int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d) int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) { + int rv = 0; if (pkey == NULL) { ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER); return 0; } - return ssl_set_pkey(ctx->cert, pkey, ctx); + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + rv = ssl_set_pkey(ctx->cnf->cert, pkey, ctx); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return rv; } int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type) @@ -388,10 +401,13 @@ int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type) } if (type == SSL_FILETYPE_PEM) { j = ERR_R_PEM_LIB; - pkey = PEM_read_bio_PrivateKey_ex(in, NULL, - ctx->default_passwd_callback, - ctx->default_passwd_callback_userdata, - ctx->libctx, ctx->propq); + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + pkey = PEM_read_bio_PrivateKey_ex(in, NULL, + ctx->cnf->default_passwd_callback, + ctx->cnf->default_passwd_callback_userdata, + ctx->libctx, ctx->propq); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } else if (type == SSL_FILETYPE_ASN1) { j = ERR_R_ASN1_LIB; pkey = d2i_PrivateKey_ex_bio(in, NULL, ctx->libctx, ctx->propq); @@ -439,8 +455,8 @@ static int use_certificate_chain_file(SSL_CTX *ctx, SSL *ssl, const char *file) BIO *in; int ret = 0; X509 *x = NULL; - pem_password_cb *passwd_callback; - void *passwd_callback_userdata; + pem_password_cb *passwd_callback = NULL; + void *passwd_callback_userdata = NULL; SSL_CTX *real_ctx = (ssl == NULL) ? ctx : ssl->ctx; if (ctx == NULL && ssl == NULL) @@ -450,8 +466,11 @@ static int use_certificate_chain_file(SSL_CTX *ctx, SSL *ssl, const char *file) * SSL_CTX_use_certificate() */ if (ctx != NULL) { - passwd_callback = ctx->default_passwd_callback; - passwd_callback_userdata = ctx->default_passwd_callback_userdata; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + passwd_callback = ctx->cnf->default_passwd_callback; + passwd_callback_userdata = ctx->cnf->default_passwd_callback_userdata; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } else { SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(ssl); @@ -798,17 +817,30 @@ int SSL_CTX_use_serverinfo_ex(SSL_CTX *ctx, unsigned int version, ERR_raise(ERR_LIB_SSL, SSL_R_INVALID_SERVERINFO_DATA); return 0; } - if (ctx->cert->key == NULL) { - ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR); - return 0; + + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + if (ctx->cnf->cert->key == NULL) { + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR); + return 0; + } + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + new_serverinfo = OPENSSL_realloc(ctx->cnf->cert->key->serverinfo, + serverinfo_length); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); } - new_serverinfo = OPENSSL_realloc(ctx->cert->key->serverinfo, - serverinfo_length); if (new_serverinfo == NULL) return 0; - ctx->cert->key->serverinfo = new_serverinfo; - memcpy(ctx->cert->key->serverinfo, serverinfo, serverinfo_length); - ctx->cert->key->serverinfo_length = serverinfo_length; + + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->cert->key->serverinfo = new_serverinfo; + memcpy(ctx->cnf->cert->key->serverinfo, serverinfo, serverinfo_length); + ctx->cnf->cert->key->serverinfo_length = serverinfo_length; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } /* * Now that the serverinfo is validated and stored, go ahead and @@ -949,7 +981,7 @@ static int ssl_set_cert_and_key(SSL *ssl, SSL_CTX *ctx, X509 *x509, EVP_PKEY *pr size_t i; int j; int rv; - CERT *c; + CERT *c = NULL; STACK_OF(X509) *dup_chain = NULL; EVP_PKEY *pubkey = NULL; SSL_CONNECTION *sc = NULL; @@ -958,7 +990,14 @@ static int ssl_set_cert_and_key(SSL *ssl, SSL_CTX *ctx, X509 *x509, EVP_PKEY *pr (sc = SSL_CONNECTION_FROM_SSL(ssl)) == NULL) return 0; - c = sc != NULL ? sc->cert : ctx->cert; + if (sc != NULL) + c = sc->cert; + else { + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + c = ctx->cnf->cert; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + } /* Do all security checks before anything else */ rv = ssl_security_cert(sc, ctx, x509, 0, 1); if (rv != 1) { diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c index 3dcc4d81e5bc63..46d34ba41b1c4f 100644 --- a/ssl/ssl_sess.c +++ b/ssl/ssl_sess.c @@ -377,8 +377,13 @@ int ssl_generate_session_id(SSL_CONNECTION *s, SSL_SESSION *ss) } if (s->generate_session_id) cb = s->generate_session_id; - else if (s->session_ctx->generate_session_id) - cb = s->session_ctx->generate_session_id; + else { + if (CRYPTO_THREAD_read_lock(s->session_ctx->cnf->cnf_lock)) { + if (s->session_ctx->cnf->generate_session_id) + cb = s->session_ctx->cnf->generate_session_id; + CRYPTO_THREAD_unlock(s->session_ctx->cnf->cnf_lock); + } + } CRYPTO_THREAD_unlock(s->session_ctx->lock); CRYPTO_THREAD_unlock(ssl->lock); /* Choose a session ID */ @@ -423,10 +428,13 @@ int ssl_get_new_session(SSL_CONNECTION *s, int session) } /* If the context has a default timeout, use it */ - if (ossl_time_is_zero(s->session_ctx->session_timeout)) - ss->timeout = SSL_CONNECTION_GET_SSL(s)->method->get_timeout(); - else - ss->timeout = s->session_ctx->session_timeout; + if (CRYPTO_THREAD_read_lock(s->session_ctx->cnf->cnf_lock)) { + if (ossl_time_is_zero(s->session_ctx->cnf->session_timeout)) + ss->timeout = SSL_CONNECTION_GET_SSL(s)->method->get_timeout(); + else + ss->timeout = s->session_ctx->cnf->session_timeout; + CRYPTO_THREAD_unlock(s->session_ctx->cnf->cnf_lock); + } ssl_session_calculate_timeout(ss); SSL_SESSION_free(s->session); @@ -472,8 +480,15 @@ SSL_SESSION *lookup_sess_in_cache(SSL_CONNECTION *s, size_t sess_id_len) { SSL_SESSION *ret = NULL; + uint32_t cache_mode = 0; + GET_SESSION_CB session_cb = NULL; - if ((s->session_ctx->session_cache_mode + if (CRYPTO_THREAD_read_lock(s->session_ctx->cnf->cnf_lock)) { + cache_mode = s->session_ctx->cnf->session_cache_mode; + CRYPTO_THREAD_unlock(s->session_ctx->cnf->cnf_lock); + } + + if ((cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP) == 0) { SSL_SESSION data; @@ -496,10 +511,15 @@ SSL_SESSION *lookup_sess_in_cache(SSL_CONNECTION *s, ssl_tsan_counter(s->session_ctx, &s->session_ctx->stats.sess_miss); } - if (ret == NULL && s->session_ctx->get_session_cb != NULL) { + if (CRYPTO_THREAD_read_lock(s->session_ctx->cnf->cnf_lock)) { + session_cb = s->session_ctx->cnf->get_session_cb; + CRYPTO_THREAD_unlock(s->session_ctx->cnf->cnf_lock); + } + + if (ret == NULL && session_cb != NULL) { int copy = 1; - ret = s->session_ctx->get_session_cb(SSL_CONNECTION_GET_SSL(s), + ret = session_cb(SSL_CONNECTION_GET_SSL(s), sess_id, sess_id_len, ©); if (ret != NULL) { @@ -520,7 +540,7 @@ SSL_SESSION *lookup_sess_in_cache(SSL_CONNECTION *s, * Add the externally cached session to the internal cache as * well if and only if we are supposed to. */ - if ((s->session_ctx->session_cache_mode & + if ((cache_mode & SSL_SESS_CACHE_NO_INTERNAL_STORE) == 0) { /* * Either return value of SSL_CTX_add_session should not @@ -735,10 +755,13 @@ int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) s = c; } - /* Adjust last used time, and add back into the cache at the appropriate spot */ - if (ctx->session_cache_mode & SSL_SESS_CACHE_UPDATE_TIME) { - c->time = ossl_time_now(); - ssl_session_calculate_timeout(c); + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + /* Adjust last used time, and add back into the cache at the appropriate spot */ + if (ctx->cnf->session_cache_mode & SSL_SESS_CACHE_UPDATE_TIME) { + c->time = ossl_time_now(); + ssl_session_calculate_timeout(c); + } + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); } if (s == NULL) { @@ -799,8 +822,11 @@ static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck) if (lck) CRYPTO_THREAD_unlock(ctx->lock); - if (ctx->remove_session_cb != NULL) - ctx->remove_session_cb(ctx, c); + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + if (ctx->cnf->remove_session_cb != NULL) + ctx->cnf->remove_session_cb(ctx, c); + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } if (ret) SSL_SESSION_free(r); @@ -1080,16 +1106,27 @@ long SSL_CTX_set_timeout(SSL_CTX *s, long t) if (s == NULL) return 0; - l = (long)ossl_time2seconds(s->session_timeout); - s->session_timeout = ossl_seconds2time(t); + l = (long)ossl_time2seconds(s->cnf->session_timeout); + if (CRYPTO_THREAD_write_lock(s->cnf->cnf_lock)) { + s->cnf->session_timeout = ossl_seconds2time(t); + CRYPTO_THREAD_unlock(s->cnf->cnf_lock); + } return l; } long SSL_CTX_get_timeout(const SSL_CTX *s) { + long ret = 0; + if (s == NULL) return 0; - return (long)ossl_time2seconds(s->session_timeout); + + if (CRYPTO_THREAD_read_lock(s->cnf->cnf_lock)) { + ret = (long)ossl_time2seconds(s->cnf->session_timeout); + CRYPTO_THREAD_unlock(s->cnf->cnf_lock); + } + + return ret; } int SSL_set_session_secret_cb(SSL *s, @@ -1176,8 +1213,11 @@ void SSL_CTX_flush_sessions(SSL_CTX *s, long t) lh_SSL_SESSION_delete(s->sessions, current); SSL_SESSION_list_remove(s, current); current->not_resumable = 1; - if (s->remove_session_cb != NULL) - s->remove_session_cb(s, current); + if (CRYPTO_THREAD_read_lock(s->cnf->cnf_lock)) { + if (s->cnf->remove_session_cb != NULL) + s->cnf->remove_session_cb(s, current); + CRYPTO_THREAD_unlock(s->cnf->cnf_lock); + } /* * Throw the session on a stack, it's entirely plausible * that while freeing outside the critical section, the @@ -1293,22 +1333,42 @@ static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s) void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx, int (*cb) (struct ssl_st *ssl, SSL_SESSION *sess)) { - ctx->new_session_cb = cb; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->new_session_cb = cb; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx)) (SSL *ssl, SSL_SESSION *sess) { - return ctx->new_session_cb; + NEW_SESSION_CB ret = NULL; + + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ctx->cnf->new_session_cb; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + + return ret; } void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx, void (*cb) (SSL_CTX *ctx, SSL_SESSION *sess)) { - ctx->remove_session_cb = cb; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->remove_session_cb = cb; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx)) (SSL_CTX *ctx, SSL_SESSION *sess) { - return ctx->remove_session_cb; + REMOVE_SESSION_CB ret = NULL; + + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ctx->cnf->remove_session_cb; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + + return ret; } void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, @@ -1316,37 +1376,65 @@ void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, const unsigned char *data, int len, int *copy)) { - ctx->get_session_cb = cb; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->get_session_cb = cb; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx)) (SSL *ssl, const unsigned char *data, int len, int *copy) { - return ctx->get_session_cb; + GET_SESSION_CB ret = NULL; + + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ctx->cnf->get_session_cb; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + + return ret; } void SSL_CTX_set_info_callback(SSL_CTX *ctx, void (*cb) (const SSL *ssl, int type, int val)) { - ctx->info_callback = cb; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->info_callback = cb; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } void (*SSL_CTX_get_info_callback(SSL_CTX *ctx)) (const SSL *ssl, int type, int val) { - return ctx->info_callback; + INFO_CALLBACK ret = NULL; + + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ctx->cnf->info_callback; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + + return ret; } void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, int (*cb) (SSL *ssl, X509 **x509, EVP_PKEY **pkey)) { - ctx->client_cert_cb = cb; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->client_cert_cb = cb; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx)) (SSL *ssl, X509 **x509, EVP_PKEY **pkey) { - return ctx->client_cert_cb; + CLIENT_CERT_CB ret = NULL; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = ctx->cnf->client_cert_cb; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return ret; } void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx, @@ -1354,7 +1442,10 @@ void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx, unsigned char *cookie, unsigned int *cookie_len)) { - ctx->app_gen_cookie_cb = cb; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->app_gen_cookie_cb = cb; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, @@ -1362,7 +1453,10 @@ void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, const unsigned char *cookie, unsigned int cookie_len)) { - ctx->app_verify_cookie_cb = cb; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->app_verify_cookie_cb = cb; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } int SSL_SESSION_set1_ticket_appdata(SSL_SESSION *ss, const void *data, size_t len) @@ -1394,7 +1488,10 @@ void SSL_CTX_set_stateless_cookie_generate_cb( unsigned char *cookie, size_t *cookie_len)) { - ctx->gen_stateless_cookie_cb = cb; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->gen_stateless_cookie_cb = cb; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } void SSL_CTX_set_stateless_cookie_verify_cb( @@ -1403,7 +1500,10 @@ void SSL_CTX_set_stateless_cookie_verify_cb( const unsigned char *cookie, size_t cookie_len)) { - ctx->verify_stateless_cookie_cb = cb; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->verify_stateless_cookie_cb = cb; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } } IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION) diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c index 0a64ca2246987e..c75060cfab87b4 100644 --- a/ssl/statem/extensions.c +++ b/ssl/statem/extensions.c @@ -997,12 +997,15 @@ static int final_server_name(SSL_CONNECTION *s, unsigned int context, int sent) return 0; } - if (sctx->ext.servername_cb != NULL) - ret = sctx->ext.servername_cb(ssl, &altmp, - sctx->ext.servername_arg); - else if (s->session_ctx->ext.servername_cb != NULL) - ret = s->session_ctx->ext.servername_cb(ssl, &altmp, - s->session_ctx->ext.servername_arg); + if (CRYPTO_THREAD_read_lock(sctx->cnf->cnf_lock)) { + if (sctx->cnf->ext.servername_cb != NULL) + ret = sctx->cnf->ext.servername_cb(ssl, &altmp, + sctx->cnf->ext.servername_arg); + else if (s->session_ctx->cnf->ext.servername_cb != NULL) + ret = s->session_ctx->cnf->ext.servername_cb(ssl, &altmp, + s->session_ctx->cnf->ext.servername_arg); + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + } /* * For servers, propagate the SNI hostname from the temporary diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c index 381a6c9d7b9099..6c4bb881353b1b 100644 --- a/ssl/statem/extensions_clnt.c +++ b/ssl/statem/extensions_clnt.c @@ -390,9 +390,14 @@ EXT_RETURN tls_construct_ctos_npn(SSL_CONNECTION *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { - if (SSL_CONNECTION_GET_CTX(s)->ext.npn_select_cb == NULL - || !SSL_IS_FIRST_HANDSHAKE(s)) - return EXT_RETURN_NOT_SENT; + if (CRYPTO_THREAD_read_lock(SSL_CONNECTION_GET_CTX(s)->cnf->cnf_lock)) { + if (SSL_CONNECTION_GET_CTX(s)->cnf->ext.npn_select_cb == NULL + || !SSL_IS_FIRST_HANDSHAKE(s)) { + CRYPTO_THREAD_unlock(SSL_CONNECTION_GET_CTX(s)->cnf->cnf_lock); + return EXT_RETURN_NOT_SENT; + } + CRYPTO_THREAD_unlock(SSL_CONNECTION_GET_CTX(s)->cnf->cnf_lock); + } /* * The client advertises an empty extension to indicate its support @@ -1546,9 +1551,13 @@ int tls_parse_stoc_npn(SSL_CONNECTION *s, PACKET *pkt, unsigned int context, return 1; /* We must have requested it. */ - if (sctx->ext.npn_select_cb == NULL) { - SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION, SSL_R_BAD_EXTENSION); - return 0; + if (CRYPTO_THREAD_read_lock(sctx->cnf->cnf_lock)) { + if (sctx->cnf->ext.npn_select_cb == NULL) { + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION, SSL_R_BAD_EXTENSION); + return 0; + } + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); } /* The data must be valid */ @@ -1557,13 +1566,17 @@ int tls_parse_stoc_npn(SSL_CONNECTION *s, PACKET *pkt, unsigned int context, /* SSLfatal() already called */ return 0; } - if (sctx->ext.npn_select_cb(SSL_CONNECTION_GET_SSL(s), - &selected, &selected_len, - PACKET_data(pkt), PACKET_remaining(pkt), - sctx->ext.npn_select_cb_arg) != - SSL_TLSEXT_ERR_OK) { - SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_BAD_EXTENSION); - return 0; + if (CRYPTO_THREAD_read_lock(sctx->cnf->cnf_lock)) { + if (sctx->cnf->ext.npn_select_cb(SSL_CONNECTION_GET_SSL(s), + &selected, &selected_len, + PACKET_data(pkt), PACKET_remaining(pkt), + sctx->cnf->ext.npn_select_cb_arg) != + SSL_TLSEXT_ERR_OK) { + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_BAD_EXTENSION); + return 0; + } + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); } /* diff --git a/ssl/statem/extensions_cust.c b/ssl/statem/extensions_cust.c index fd840e8918e833..857aaa7f345f11 100644 --- a/ssl/statem/extensions_cust.c +++ b/ssl/statem/extensions_cust.c @@ -349,8 +349,15 @@ void custom_exts_free(custom_ext_methods *exts) /* Return true if a client custom extension exists, false otherwise */ int SSL_CTX_has_client_custom_ext(const SSL_CTX *ctx, unsigned int ext_type) { - return custom_ext_find(&ctx->cert->custext, ENDPOINT_CLIENT, ext_type, - NULL) != NULL; + int ret = 0; + + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + ret = custom_ext_find(&ctx->cnf->cert->custext, ENDPOINT_CLIENT, ext_type, + NULL) != NULL; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + + return ret; } int ossl_tls_add_custom_ext_intern(SSL_CTX *ctx, custom_ext_methods *exts, @@ -371,8 +378,12 @@ int ossl_tls_add_custom_ext_intern(SSL_CTX *ctx, custom_ext_methods *exts, if (add_cb == NULL && free_cb != NULL) return 0; - if (exts == NULL) - exts = &ctx->cert->custext; + if (exts == NULL) { + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + exts = &ctx->cnf->cert->custext; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + } #ifndef OPENSSL_NO_CT /* diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c index 21db977c88f3d3..1063c70cdc9a91 100644 --- a/ssl/statem/extensions_srvr.c +++ b/ssl/statem/extensions_srvr.c @@ -721,7 +721,7 @@ int tls_parse_ctos_cookie(SSL_CONNECTION *s, PACKET *pkt, unsigned int context, #ifndef OPENSSL_NO_TLS1_3 unsigned int format, version, key_share, group_id; EVP_MD_CTX *hctx; - EVP_PKEY *pkey; + EVP_PKEY *pkey = NULL; PACKET cookie, raw, chhash, appcookie; WPACKET hrrpkt; const unsigned char *data, *mdin, *ciphdata; @@ -731,9 +731,15 @@ int tls_parse_ctos_cookie(SSL_CONNECTION *s, PACKET *pkt, unsigned int context, uint64_t tm, now; SSL *ssl = SSL_CONNECTION_GET_SSL(s); SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s); + VERIFY_STATELESS_COOKIE_CB verify_stateless_cookie_cb = NULL; + + if (CRYPTO_THREAD_read_lock(sctx->cnf->cnf_lock)) { + verify_stateless_cookie_cb = sctx->cnf->verify_stateless_cookie_cb; + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + } /* Ignore any cookie if we're not set up to verify it */ - if (sctx->verify_stateless_cookie_cb == NULL + if (verify_stateless_cookie_cb == NULL || (s->s3.flags & TLS1_FLAGS_STATELESS) == 0) return 1; @@ -754,10 +760,14 @@ int tls_parse_ctos_cookie(SSL_CONNECTION *s, PACKET *pkt, unsigned int context, /* Verify the HMAC of the cookie */ hctx = EVP_MD_CTX_create(); - pkey = EVP_PKEY_new_raw_private_key_ex(sctx->libctx, "HMAC", - sctx->propq, - s->session_ctx->ext.cookie_hmac_key, - sizeof(s->session_ctx->ext.cookie_hmac_key)); + if (CRYPTO_THREAD_read_lock(s->session_ctx->cnf->cnf_lock)) { + pkey = EVP_PKEY_new_raw_private_key_ex(sctx->libctx, "HMAC", + sctx->propq, + s->session_ctx->cnf->ext.cookie_hmac_key, + sizeof(s->session_ctx->cnf->ext.cookie_hmac_key)); + CRYPTO_THREAD_unlock(s->session_ctx->cnf->cnf_lock); + } + if (hctx == NULL || pkey == NULL) { EVP_MD_CTX_free(hctx); EVP_PKEY_free(pkey); @@ -847,7 +857,7 @@ int tls_parse_ctos_cookie(SSL_CONNECTION *s, PACKET *pkt, unsigned int context, } /* Verify the app cookie */ - if (sctx->verify_stateless_cookie_cb(ssl, + if (verify_stateless_cookie_cb(ssl, PACKET_data(&appcookie), PACKET_remaining(&appcookie)) == 0) { SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_COOKIE_MISMATCH); @@ -1494,16 +1504,23 @@ EXT_RETURN tls_construct_stoc_next_proto_neg(SSL_CONNECTION *s, WPACKET *pkt, { const unsigned char *npa; unsigned int npalen; - int ret; + int ret = 0; int npn_seen = s->s3.npn_seen; SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s); s->s3.npn_seen = 0; - if (!npn_seen || sctx->ext.npn_advertised_cb == NULL) - return EXT_RETURN_NOT_SENT; - ret = sctx->ext.npn_advertised_cb(SSL_CONNECTION_GET_SSL(s), &npa, &npalen, - sctx->ext.npn_advertised_cb_arg); + if (CRYPTO_THREAD_read_lock(sctx->cnf->cnf_lock)) { + if (!npn_seen || sctx->cnf->ext.npn_advertised_cb == NULL) { + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + return EXT_RETURN_NOT_SENT; + } + + ret = sctx->cnf->ext.npn_advertised_cb(SSL_CONNECTION_GET_SSL(s), &npa, &npalen, + sctx->cnf->ext.npn_advertised_cb_arg); + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + } + if (ret == SSL_TLSEXT_ERR_OK) { if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg) || !WPACKET_sub_memcpy_u16(pkt, npa, npalen)) { @@ -1771,15 +1788,21 @@ EXT_RETURN tls_construct_stoc_cookie(SSL_CONNECTION *s, WPACKET *pkt, unsigned char *hmac, *hmac2; size_t startlen, ciphlen, totcookielen, hashlen, hmaclen, appcookielen; EVP_MD_CTX *hctx; - EVP_PKEY *pkey; + EVP_PKEY *pkey = NULL; int ret = EXT_RETURN_FAIL; SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s); SSL *ssl = SSL_CONNECTION_GET_SSL(s); + GEN_STATELESS_COOKIE_CB gen_stateless_cookie_cb = NULL; if ((s->s3.flags & TLS1_FLAGS_STATELESS) == 0) return EXT_RETURN_NOT_SENT; - if (sctx->gen_stateless_cookie_cb == NULL) { + if (CRYPTO_THREAD_read_lock(sctx->cnf->cnf_lock)) { + gen_stateless_cookie_cb = sctx->cnf->gen_stateless_cookie_cb; + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + } + + if (gen_stateless_cookie_cb == NULL) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_NO_COOKIE_CALLBACK_SET); return EXT_RETURN_FAIL; } @@ -1824,7 +1847,7 @@ EXT_RETURN tls_construct_stoc_cookie(SSL_CONNECTION *s, WPACKET *pkt, } /* Generate the application cookie */ - if (sctx->gen_stateless_cookie_cb(ssl, appcookie1, + if (gen_stateless_cookie_cb(ssl, appcookie1, &appcookielen) == 0) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_COOKIE_GEN_CALLBACK_FAILURE); return EXT_RETURN_FAIL; @@ -1848,10 +1871,13 @@ EXT_RETURN tls_construct_stoc_cookie(SSL_CONNECTION *s, WPACKET *pkt, /* HMAC the cookie */ hctx = EVP_MD_CTX_create(); - pkey = EVP_PKEY_new_raw_private_key_ex(sctx->libctx, "HMAC", - sctx->propq, - s->session_ctx->ext.cookie_hmac_key, - sizeof(s->session_ctx->ext.cookie_hmac_key)); + if (CRYPTO_THREAD_read_lock(s->session_ctx->cnf->cnf_lock)) { + pkey = EVP_PKEY_new_raw_private_key_ex(sctx->libctx, "HMAC", + sctx->propq, + s->session_ctx->cnf->ext.cookie_hmac_key, + sizeof(s->session_ctx->cnf->ext.cookie_hmac_key)); + CRYPTO_THREAD_unlock(s->session_ctx->cnf->cnf_lock); + } if (hctx == NULL || pkey == NULL) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB); goto err; diff --git a/ssl/statem/statem.c b/ssl/statem/statem.c index 921d7cfb1e05df..4fdebcdf569cf3 100644 --- a/ssl/statem/statem.c +++ b/ssl/statem/statem.c @@ -312,13 +312,19 @@ typedef void (*info_cb) (const SSL *, int, int); static info_cb get_callback(SSL_CONNECTION *s) { SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s); + info_cb ret = NULL; if (s->info_callback != NULL) return s->info_callback; - else if (sctx->info_callback != NULL) - return sctx->info_callback; + else { + if (CRYPTO_THREAD_read_lock(sctx->cnf->cnf_lock)) { + if (sctx->cnf->info_callback != NULL) + ret = sctx->cnf->info_callback; + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + } + } - return NULL; + return ret; } /* diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c index 922f8a1119e183..d1044baee8f509 100644 --- a/ssl/statem/statem_clnt.c +++ b/ssl/statem/statem_clnt.c @@ -2727,6 +2727,7 @@ MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL_CONNECTION *s, */ if (SSL_CONNECTION_IS_TLS13(s) || s->session->session_id_length > 0) { SSL_SESSION *new_sess; + uint32_t cache_mode = 0; /* * We reused an existing session, so we need to replace it with a new @@ -2737,7 +2738,11 @@ MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL_CONNECTION *s, goto err; } - if ((s->session_ctx->session_cache_mode & SSL_SESS_CACHE_CLIENT) != 0 + if (CRYPTO_THREAD_read_lock(s->session_ctx->cnf->cnf_lock)) { + cache_mode = s->session_ctx->cnf->session_cache_mode; + CRYPTO_THREAD_unlock(s->session_ctx->cnf->cnf_lock); + } + if ((cache_mode & SSL_SESS_CACHE_CLIENT) != 0 && !SSL_CONNECTION_IS_TLS13(s)) { /* * In TLSv1.2 and below the arrival of a new tickets signals that @@ -2931,21 +2936,26 @@ int tls_process_initial_server_flight(SSL_CONNECTION *s) * |ext.ocsp.resp_len| values will be set if we actually received a status * message, or NULL and -1 otherwise */ - if (s->ext.status_type != TLSEXT_STATUSTYPE_nothing - && sctx->ext.status_cb != NULL) { - int ret = sctx->ext.status_cb(SSL_CONNECTION_GET_SSL(s), - sctx->ext.status_arg); - - if (ret == 0) { - SSLfatal(s, SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE, - SSL_R_INVALID_STATUS_RESPONSE); - return 0; - } - if (ret < 0) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, - SSL_R_OCSP_CALLBACK_FAILURE); - return 0; + if (CRYPTO_THREAD_read_lock(sctx->cnf->cnf_lock)) { + if (s->ext.status_type != TLSEXT_STATUSTYPE_nothing + && sctx->cnf->ext.status_cb != NULL) { + int ret = sctx->cnf->ext.status_cb(SSL_CONNECTION_GET_SSL(s), + sctx->cnf->ext.status_arg); + + if (ret == 0) { + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + SSLfatal(s, SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE, + SSL_R_INVALID_STATUS_RESPONSE); + return 0; + } + if (ret < 0) { + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_R_OCSP_CALLBACK_FAILURE); + return 0; + } } + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); } #ifndef OPENSSL_NO_CT if (s->ct_validation_callback != NULL) { @@ -4051,14 +4061,22 @@ int ssl_do_client_cert_cb(SSL_CONNECTION *s, X509 **px509, EVP_PKEY **ppkey) SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s); #ifndef OPENSSL_NO_ENGINE - if (sctx->client_cert_engine) { - i = tls_engine_load_ssl_client_cert(s, px509, ppkey); - if (i != 0) - return i; + if (CRYPTO_THREAD_read_lock(sctx->cnf->cnf_lock)) { + if (sctx->cnf->client_cert_engine) { + i = tls_engine_load_ssl_client_cert(s, px509, ppkey); + if (i != 0) { + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + return i; + } + } + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); } #endif - if (sctx->client_cert_cb) - i = sctx->client_cert_cb(SSL_CONNECTION_GET_SSL(s), px509, ppkey); + if (CRYPTO_THREAD_read_lock(sctx->cnf->cnf_lock)) { + if (sctx->cnf->client_cert_cb) + i = sctx->cnf->client_cert_cb(SSL_CONNECTION_GET_SSL(s), px509, ppkey); + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + } return i; } diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c index 16b5f590a0b1bc..f2726bdd18b928 100644 --- a/ssl/statem/statem_lib.c +++ b/ssl/statem/statem_lib.c @@ -997,9 +997,9 @@ static int ssl_add_cert_chain(SSL_CONNECTION *s, WPACKET *pkt, CERT_PKEY *cpk, i { int i, chain_count; X509 *x; - STACK_OF(X509) *extra_certs; + STACK_OF(X509) *extra_certs = NULL; STACK_OF(X509) *chain = NULL; - X509_STORE *chain_store; + X509_STORE *chain_store = NULL; SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s); if (cpk == NULL || cpk->x509 == NULL) @@ -1012,15 +1012,23 @@ static int ssl_add_cert_chain(SSL_CONNECTION *s, WPACKET *pkt, CERT_PKEY *cpk, i */ if (cpk->chain != NULL) extra_certs = cpk->chain; - else - extra_certs = sctx->extra_certs; + else { + if (CRYPTO_THREAD_read_lock(sctx->cnf->cnf_lock)) { + extra_certs = sctx->cnf->extra_certs; + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + } + } if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || extra_certs) chain_store = NULL; else if (s->cert->chain_store) chain_store = s->cert->chain_store; - else - chain_store = sctx->cert_store; + else { + if (CRYPTO_THREAD_read_lock(sctx->cnf->cnf_lock)) { + chain_store = sctx->cnf->cert_store; + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + } + } if (chain_store != NULL) { X509_STORE_CTX *xs_ctx = X509_STORE_CTX_new_ex(sctx->libctx, @@ -1473,8 +1481,12 @@ WORK_STATE tls_finish_handshake(SSL_CONNECTION *s, ossl_unused WORK_STATE wst, * We encourage applications to only use TLSv1.3 tickets once, * so we remove this one from the cache. */ - if ((s->session_ctx->session_cache_mode - & SSL_SESS_CACHE_CLIENT) != 0) + uint32_t cache_mode = 0; + if (CRYPTO_THREAD_read_lock(s->session_ctx->cnf->cnf_lock)) { + cache_mode = s->session_ctx->cnf->session_cache_mode; + CRYPTO_THREAD_unlock(s->session_ctx->cnf->cnf_lock); + } + if ((cache_mode & SSL_SESS_CACHE_CLIENT) != 0) SSL_CTX_remove_session(s->session_ctx, s->session); } else { /* @@ -1503,8 +1515,13 @@ WORK_STATE tls_finish_handshake(SSL_CONNECTION *s, ossl_unused WORK_STATE wst, if (s->info_callback != NULL) cb = s->info_callback; - else if (sctx->info_callback != NULL) - cb = sctx->info_callback; + else { + if (CRYPTO_THREAD_read_lock(sctx->cnf->cnf_lock)) { + if (sctx->cnf->info_callback != NULL) + cb = sctx->cnf->info_callback; + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + } + } /* The callback may expect us to not be in init at handshake done */ ossl_statem_set_in_init(s, 0); @@ -1908,9 +1925,14 @@ static int is_tls13_capable(const SSL_CONNECTION *s) * A servername callback can change the available certs, so if a servername * cb is set then we just assume TLSv1.3 will be ok */ - if (sctx->ext.servername_cb != NULL - || s->session_ctx->ext.servername_cb != NULL) - return 1; + if (CRYPTO_THREAD_read_lock(sctx->cnf->cnf_lock)) { + if (sctx->cnf->ext.servername_cb != NULL + || s->session_ctx->cnf->ext.servername_cb != NULL) { + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + return 1; + } + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + } #ifndef OPENSSL_NO_PSK if (s->psk_server_callback != NULL) diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index da77c16e6b288b..ef3845054e2fcd 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -1381,9 +1381,14 @@ CON_FUNC_RETURN dtls_construct_hello_verify_request(SSL_CONNECTION *s, { unsigned int cookie_leni; SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s); + APP_GEN_COOKIE_CB gen_cookie_cb = NULL; - if (sctx->app_gen_cookie_cb == NULL - || sctx->app_gen_cookie_cb(SSL_CONNECTION_GET_SSL(s), s->d1->cookie, + if (CRYPTO_THREAD_read_lock(sctx->cnf->cnf_lock)) { + gen_cookie_cb = sctx->cnf->app_gen_cookie_cb; + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + } + if (gen_cookie_cb == NULL + || gen_cookie_cb(SSL_CONNECTION_GET_SSL(s), s->d1->cookie, &cookie_leni) == 0 || cookie_leni > DTLS1_COOKIE_LENGTH) { SSLfatal(s, SSL_AD_NO_ALERT, SSL_R_COOKIE_GEN_CALLBACK_FAILURE); @@ -1700,19 +1705,25 @@ static int tls_early_post_process_client_hello(SSL_CONNECTION *s) /* Finished parsing the ClientHello, now we can start processing it */ /* Give the ClientHello callback a crack at things */ - if (sctx->client_hello_cb != NULL) { - /* A failure in the ClientHello callback terminates the connection. */ - switch (sctx->client_hello_cb(ssl, &al, sctx->client_hello_cb_arg)) { - case SSL_CLIENT_HELLO_SUCCESS: - break; - case SSL_CLIENT_HELLO_RETRY: - s->rwstate = SSL_CLIENT_HELLO_CB; - return -1; - case SSL_CLIENT_HELLO_ERROR: - default: - SSLfatal(s, al, SSL_R_CALLBACK_FAILED); - goto err; + if (CRYPTO_THREAD_read_lock(sctx->cnf->cnf_lock)) { + if (sctx->cnf->client_hello_cb != NULL) { + /* A failure in the ClientHello callback terminates the connection. */ + int val = sctx->cnf->client_hello_cb(ssl, &al, sctx->cnf->client_hello_cb_arg); + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + switch (val) { + case SSL_CLIENT_HELLO_SUCCESS: + break; + case SSL_CLIENT_HELLO_RETRY: + s->rwstate = SSL_CLIENT_HELLO_CB; + return -1; + case SSL_CLIENT_HELLO_ERROR: + default: + SSLfatal(s, al, SSL_R_CALLBACK_FAILED); + goto err; + } } + else + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); } /* Set up the client_random */ @@ -1757,8 +1768,13 @@ static int tls_early_post_process_client_hello(SSL_CONNECTION *s) if (SSL_CONNECTION_IS_DTLS(s)) { /* Empty cookie was already handled above by returning early. */ if (SSL_get_options(ssl) & SSL_OP_COOKIE_EXCHANGE) { - if (sctx->app_verify_cookie_cb != NULL) { - if (sctx->app_verify_cookie_cb(ssl, clienthello->dtls_cookie, + APP_VERIFY_COOKIE_CB verify_cookie_cb = NULL; + if (CRYPTO_THREAD_read_lock(sctx->cnf->cnf_lock)) { + verify_cookie_cb = sctx->cnf->app_verify_cookie_cb; + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + } + if (verify_cookie_cb != NULL) { + if (verify_cookie_cb(ssl, clienthello->dtls_cookie, clienthello->dtls_cookie_len) == 0) { SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_COOKIE_MISMATCH); @@ -2151,36 +2167,44 @@ static int tls_handle_status_request(SSL_CONNECTION *s) * and must be called after the cipher has been chosen because this may * influence which certificate is sent */ - if (s->ext.status_type != TLSEXT_STATUSTYPE_nothing && sctx != NULL - && sctx->ext.status_cb != NULL) { - int ret; + if (CRYPTO_THREAD_read_lock(sctx->cnf->cnf_lock)) { + if (s->ext.status_type != TLSEXT_STATUSTYPE_nothing && sctx != NULL + && sctx->cnf->ext.status_cb != NULL) { + int ret; - /* If no certificate can't return certificate status */ - if (s->s3.tmp.cert != NULL) { - /* + /* If no certificate can't return certificate status */ + if (s->s3.tmp.cert != NULL) { + /* * Set current certificate to one we will use so SSL_get_certificate * et al can pick it up. */ - s->cert->key = s->s3.tmp.cert; - ret = sctx->ext.status_cb(SSL_CONNECTION_GET_SSL(s), - sctx->ext.status_arg); - switch (ret) { + s->cert->key = s->s3.tmp.cert; + ret = sctx->cnf->ext.status_cb(SSL_CONNECTION_GET_SSL(s), + sctx->cnf->ext.status_arg); + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + + switch (ret) { /* We don't want to send a status request response */ - case SSL_TLSEXT_ERR_NOACK: - s->ext.status_expected = 0; - break; - /* status request response should be sent */ - case SSL_TLSEXT_ERR_OK: - if (s->ext.ocsp.resp) - s->ext.status_expected = 1; - break; - /* something bad happened */ - case SSL_TLSEXT_ERR_ALERT_FATAL: - default: - SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_CLIENTHELLO_TLSEXT); - return 0; + case SSL_TLSEXT_ERR_NOACK: + s->ext.status_expected = 0; + break; + /* status request response should be sent */ + case SSL_TLSEXT_ERR_OK: + if (s->ext.ocsp.resp) + s->ext.status_expected = 1; + break; + /* something bad happened */ + case SSL_TLSEXT_ERR_ALERT_FATAL: + default: + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_CLIENTHELLO_TLSEXT); + return 0; + } } + else + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); } + else + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); } return 1; @@ -2196,67 +2220,72 @@ int tls_handle_alpn(SSL_CONNECTION *s) unsigned char selected_len = 0; SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s); - if (sctx->ext.alpn_select_cb != NULL && s->s3.alpn_proposed != NULL) { - int r = sctx->ext.alpn_select_cb(SSL_CONNECTION_GET_SSL(s), - &selected, &selected_len, - s->s3.alpn_proposed, - (unsigned int)s->s3.alpn_proposed_len, - sctx->ext.alpn_select_cb_arg); - - if (r == SSL_TLSEXT_ERR_OK) { - OPENSSL_free(s->s3.alpn_selected); - s->s3.alpn_selected = OPENSSL_memdup(selected, selected_len); - if (s->s3.alpn_selected == NULL) { - s->s3.alpn_selected_len = 0; - SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - s->s3.alpn_selected_len = selected_len; + if (CRYPTO_THREAD_read_lock(sctx->cnf->cnf_lock)) { + if (sctx->cnf->ext.alpn_select_cb != NULL && s->s3.alpn_proposed != NULL) { + int r = sctx->cnf->ext.alpn_select_cb(SSL_CONNECTION_GET_SSL(s), + &selected, &selected_len, + s->s3.alpn_proposed, + (unsigned int)s->s3.alpn_proposed_len, + sctx->cnf->ext.alpn_select_cb_arg); + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + + if (r == SSL_TLSEXT_ERR_OK) { + OPENSSL_free(s->s3.alpn_selected); + s->s3.alpn_selected = OPENSSL_memdup(selected, selected_len); + if (s->s3.alpn_selected == NULL) { + s->s3.alpn_selected_len = 0; + SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + s->s3.alpn_selected_len = selected_len; #ifndef OPENSSL_NO_NEXTPROTONEG - /* ALPN takes precedence over NPN. */ - s->s3.npn_seen = 0; + /* ALPN takes precedence over NPN. */ + s->s3.npn_seen = 0; #endif - /* Check ALPN is consistent with session */ - if (s->session->ext.alpn_selected == NULL + /* Check ALPN is consistent with session */ + if (s->session->ext.alpn_selected == NULL || selected_len != s->session->ext.alpn_selected_len || memcmp(selected, s->session->ext.alpn_selected, selected_len) != 0) { - /* Not consistent so can't be used for early_data */ - s->ext.early_data_ok = 0; + /* Not consistent so can't be used for early_data */ + s->ext.early_data_ok = 0; - if (!s->hit) { - /* + if (!s->hit) { + /* * This is a new session and so alpn_selected should have * been initialised to NULL. We should update it with the * selected ALPN. */ - if (!ossl_assert(s->session->ext.alpn_selected == NULL)) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, - ERR_R_INTERNAL_ERROR); - return 0; - } - s->session->ext.alpn_selected = OPENSSL_memdup(selected, - selected_len); - if (s->session->ext.alpn_selected == NULL) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, - ERR_R_INTERNAL_ERROR); - return 0; + if (!ossl_assert(s->session->ext.alpn_selected == NULL)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + ERR_R_INTERNAL_ERROR); + return 0; + } + s->session->ext.alpn_selected = OPENSSL_memdup(selected, + selected_len); + if (s->session->ext.alpn_selected == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + ERR_R_INTERNAL_ERROR); + return 0; + } + s->session->ext.alpn_selected_len = selected_len; } - s->session->ext.alpn_selected_len = selected_len; } - } - return 1; - } else if (r != SSL_TLSEXT_ERR_NOACK) { - SSLfatal(s, SSL_AD_NO_APPLICATION_PROTOCOL, - SSL_R_NO_APPLICATION_PROTOCOL); - return 0; - } - /* + return 1; + } else if (r != SSL_TLSEXT_ERR_NOACK) { + SSLfatal(s, SSL_AD_NO_APPLICATION_PROTOCOL, + SSL_R_NO_APPLICATION_PROTOCOL); + return 0; + } + /* * If r == SSL_TLSEXT_ERR_NOACK then behave as if no callback was * present. */ + } + else + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); } /* Check ALPN is consistent with session */ @@ -2393,6 +2422,7 @@ CON_FUNC_RETURN tls_construct_server_hello(SSL_CONNECTION *s, WPACKET *pkt) size_t sl, len; int version; unsigned char *session_id; + uint32_t cache_mode = 0; int usetls13 = SSL_CONNECTION_IS_TLS13(s) || s->hello_retry_request == SSL_HRR_PENDING; @@ -2428,8 +2458,12 @@ CON_FUNC_RETURN tls_construct_server_hello(SSL_CONNECTION *s, WPACKET *pkt) * so the following won't overwrite an ID that we're supposed * to send back. */ + if (CRYPTO_THREAD_read_lock(SSL_CONNECTION_GET_CTX(s)->cnf->cnf_lock)) { + cache_mode = SSL_CONNECTION_GET_CTX(s)->cnf->session_cache_mode; + CRYPTO_THREAD_unlock(SSL_CONNECTION_GET_CTX(s)->cnf->cnf_lock); + } if (s->session->not_resumable || - (!(SSL_CONNECTION_GET_CTX(s)->session_cache_mode & SSL_SESS_CACHE_SERVER) + (!(cache_mode & SSL_SESS_CACHE_SERVER) && !s->hit)) s->session->session_id_length = 0; @@ -4001,80 +4035,86 @@ static CON_FUNC_RETURN construct_stateless_ticket(SSL_CONNECTION *s, * Initialize HMAC and cipher contexts. If callback present it does * all the work otherwise use generated values from parent ctx. */ + if (CRYPTO_THREAD_read_lock(tctx->cnf->cnf_lock)) { #ifndef OPENSSL_NO_DEPRECATED_3_0 - if (tctx->ext.ticket_key_evp_cb != NULL || tctx->ext.ticket_key_cb != NULL) + if (tctx->cnf->ext.ticket_key_evp_cb != NULL || tctx->cnf->ext.ticket_key_cb != NULL) #else - if (tctx->ext.ticket_key_evp_cb != NULL) + if (tctx->cnf->ext.ticket_key_evp_cb != NULL) #endif - { - int ret = 0; + { + int ret = 0; - if (tctx->ext.ticket_key_evp_cb != NULL) - ret = tctx->ext.ticket_key_evp_cb(ssl, key_name, iv, ctx, - ssl_hmac_get0_EVP_MAC_CTX(hctx), - 1); + if (tctx->cnf->ext.ticket_key_evp_cb != NULL) + ret = tctx->cnf->ext.ticket_key_evp_cb(ssl, key_name, iv, ctx, + ssl_hmac_get0_EVP_MAC_CTX(hctx), + 1); #ifndef OPENSSL_NO_DEPRECATED_3_0 - else if (tctx->ext.ticket_key_cb != NULL) - /* if 0 is returned, write an empty ticket */ - ret = tctx->ext.ticket_key_cb(ssl, key_name, iv, ctx, - ssl_hmac_get0_HMAC_CTX(hctx), 1); + else if (tctx->cnf->ext.ticket_key_cb != NULL) + /* if 0 is returned, write an empty ticket */ + ret = tctx->cnf->ext.ticket_key_cb(ssl, key_name, iv, ctx, + ssl_hmac_get0_HMAC_CTX(hctx), 1); #endif + CRYPTO_THREAD_unlock(tctx->cnf->cnf_lock); - if (ret == 0) { - /* + if (ret == 0) { + /* * In TLSv1.2 we construct a 0 length ticket. In TLSv1.3 a 0 * length ticket is not allowed so we abort construction of the * ticket */ - if (SSL_CONNECTION_IS_TLS13(s)) { - ok = CON_FUNC_DONT_SEND; + if (SSL_CONNECTION_IS_TLS13(s)) { + ok = CON_FUNC_DONT_SEND; + goto err; + } + /* Put timeout and length */ + if (!WPACKET_put_bytes_u32(pkt, 0) + || !WPACKET_put_bytes_u16(pkt, 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + goto err; + } + OPENSSL_free(senc); + EVP_CIPHER_CTX_free(ctx); + ssl_hmac_free(hctx); + return CON_FUNC_SUCCESS; + } + if (ret < 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_CALLBACK_FAILED); goto err; } - /* Put timeout and length */ - if (!WPACKET_put_bytes_u32(pkt, 0) - || !WPACKET_put_bytes_u16(pkt, 0)) { + iv_len = EVP_CIPHER_CTX_get_iv_length(ctx); + if (iv_len < 0) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); goto err; } - OPENSSL_free(senc); - EVP_CIPHER_CTX_free(ctx); - ssl_hmac_free(hctx); - return CON_FUNC_SUCCESS; - } - if (ret < 0) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_CALLBACK_FAILED); - goto err; - } - iv_len = EVP_CIPHER_CTX_get_iv_length(ctx); - if (iv_len < 0) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - goto err; - } - } else { - EVP_CIPHER *cipher = EVP_CIPHER_fetch(sctx->libctx, "AES-256-CBC", - sctx->propq); + } else { + EVP_CIPHER *cipher = EVP_CIPHER_fetch(sctx->libctx, "AES-256-CBC", + sctx->propq); - if (cipher == NULL) { - /* Error is already recorded */ - SSLfatal_alert(s, SSL_AD_INTERNAL_ERROR); - goto err; - } + if (cipher == NULL) { + CRYPTO_THREAD_unlock(tctx->cnf->cnf_lock); + /* Error is already recorded */ + SSLfatal_alert(s, SSL_AD_INTERNAL_ERROR); + goto err; + } - iv_len = EVP_CIPHER_get_iv_length(cipher); - if (iv_len < 0 - || RAND_bytes_ex(sctx->libctx, iv, iv_len, 0) <= 0 - || !EVP_EncryptInit_ex(ctx, cipher, NULL, - tctx->ext.secure->tick_aes_key, iv) - || !ssl_hmac_init(hctx, tctx->ext.secure->tick_hmac_key, - sizeof(tctx->ext.secure->tick_hmac_key), - "SHA256")) { + iv_len = EVP_CIPHER_get_iv_length(cipher); + if (iv_len < 0 + || RAND_bytes_ex(sctx->libctx, iv, iv_len, 0) <= 0 + || !EVP_EncryptInit_ex(ctx, cipher, NULL, + tctx->cnf->ext.secure->tick_aes_key, iv) + || !ssl_hmac_init(hctx, tctx->cnf->ext.secure->tick_hmac_key, + sizeof(tctx->cnf->ext.secure->tick_hmac_key), + "SHA256")) { + CRYPTO_THREAD_unlock(tctx->cnf->cnf_lock); + EVP_CIPHER_free(cipher); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + goto err; + } EVP_CIPHER_free(cipher); - SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - goto err; + memcpy(key_name, tctx->cnf->ext.tick_key_name, + sizeof(tctx->cnf->ext.tick_key_name)); + CRYPTO_THREAD_unlock(tctx->cnf->cnf_lock); } - EVP_CIPHER_free(cipher); - memcpy(key_name, tctx->ext.tick_key_name, - sizeof(tctx->ext.tick_key_name)); } if (!create_ticket_prequel(s, pkt, age_add, tick_nonce)) { @@ -4245,11 +4285,15 @@ CON_FUNC_RETURN tls_construct_new_session_ticket(SSL_CONNECTION *s, WPACKET *pkt s->session->ext.max_early_data = s->max_early_data; } - if (tctx->generate_ticket_cb != NULL && - tctx->generate_ticket_cb(SSL_CONNECTION_GET_SSL(s), - tctx->ticket_cb_data) == 0) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - goto err; + if (CRYPTO_THREAD_read_lock(tctx->cnf->cnf_lock)) { + if (tctx->cnf->generate_ticket_cb != NULL && + tctx->cnf->generate_ticket_cb(SSL_CONNECTION_GET_SSL(s), + tctx->cnf->ticket_cb_data) == 0) { + CRYPTO_THREAD_unlock(tctx->cnf->cnf_lock); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + goto err; + } + CRYPTO_THREAD_unlock(tctx->cnf->cnf_lock); } /* * If we are using anti-replay protection then we behave as if diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index de82d2b33a1e62..0e596bd0a69c73 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -404,16 +404,19 @@ int ssl_load_groups(SSL_CTX *ctx) if (num_deflt_grps == 0) return 1; - ctx->ext.supported_groups_default - = OPENSSL_malloc(sizeof(uint16_t) * num_deflt_grps); - - if (ctx->ext.supported_groups_default == NULL) - return 0; - - memcpy(ctx->ext.supported_groups_default, - tmp_supp_groups, - num_deflt_grps * sizeof(tmp_supp_groups[0])); - ctx->ext.supported_groups_default_len = num_deflt_grps; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->ext.supported_groups_default + = OPENSSL_malloc(sizeof(uint16_t) * num_deflt_grps); + if (ctx->cnf->ext.supported_groups_default == NULL) { + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + return 0; + } + memcpy(ctx->cnf->ext.supported_groups_default, + tmp_supp_groups, + num_deflt_grps * sizeof(tmp_supp_groups[0])); + ctx->cnf->ext.supported_groups_default_len = num_deflt_grps; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } return 1; } @@ -832,8 +835,11 @@ void tls1_get_supported_groups(SSL_CONNECTION *s, const uint16_t **pgroups, default: if (s->ext.supportedgroups == NULL) { - *pgroups = sctx->ext.supported_groups_default; - *pgroupslen = sctx->ext.supported_groups_default_len; + if (CRYPTO_THREAD_read_lock(sctx->cnf->cnf_lock)) { + *pgroups = sctx->cnf->ext.supported_groups_default; + *pgroupslen = sctx->cnf->ext.supported_groups_default_len; + CRYPTO_THREAD_unlock(sctx->cnf->cnf_lock); + } } else { *pgroups = s->ext.supportedgroups; *pgroupslen = s->ext.supportedgroups_len; @@ -2227,6 +2233,8 @@ SSL_TICKET_STATUS tls_decrypt_ticket(SSL_CONNECTION *s, EVP_CIPHER_CTX *ctx = NULL; SSL_CTX *tctx = s->session_ctx; SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s); + TICKET_KEY_EVP_CB ticket_key_evp_cb = NULL; + TICKET_KEY_CB ticket_key_cb = NULL; if (eticklen == 0) { /* @@ -2265,26 +2273,37 @@ SSL_TICKET_STATUS tls_decrypt_ticket(SSL_CONNECTION *s, goto end; } #ifndef OPENSSL_NO_DEPRECATED_3_0 - if (tctx->ext.ticket_key_evp_cb != NULL || tctx->ext.ticket_key_cb != NULL) + if (CRYPTO_THREAD_read_lock(tctx->cnf->cnf_lock)) { + ticket_key_evp_cb = tctx->cnf->ext.ticket_key_evp_cb; + ticket_key_cb = tctx->cnf->ext.ticket_key_cb; + CRYPTO_THREAD_unlock(tctx->cnf->cnf_lock); + } + if (ticket_key_evp_cb != NULL || ticket_key_cb != NULL) #else - if (tctx->ext.ticket_key_evp_cb != NULL) + if (CRYPTO_THREAD_read_lock(tctx->cnf->cnf_lock)) { + ticket_key_evp_cb = tctx->cnf->ext.ticket_key_evp_cb; + CRYPTO_THREAD_unlock(tctx->cnf->cnf_lock); + } + if (ticket_key_evp_cb != NULL) #endif { unsigned char *nctick = (unsigned char *)etick; int rv = 0; - if (tctx->ext.ticket_key_evp_cb != NULL) - rv = tctx->ext.ticket_key_evp_cb(SSL_CONNECTION_GET_SSL(s), nctick, + if (ticket_key_evp_cb != NULL) + rv = ticket_key_evp_cb(SSL_CONNECTION_GET_SSL(s), nctick, nctick + TLSEXT_KEYNAME_LENGTH, ctx, ssl_hmac_get0_EVP_MAC_CTX(hctx), 0); #ifndef OPENSSL_NO_DEPRECATED_3_0 - else if (tctx->ext.ticket_key_cb != NULL) - /* if 0 is returned, write an empty ticket */ - rv = tctx->ext.ticket_key_cb(SSL_CONNECTION_GET_SSL(s), nctick, - nctick + TLSEXT_KEYNAME_LENGTH, - ctx, ssl_hmac_get0_HMAC_CTX(hctx), 0); + else { + if (ticket_key_cb != NULL) + /* if 0 is returned, write an empty ticket */ + rv = ticket_key_cb(SSL_CONNECTION_GET_SSL(s), nctick, + nctick + TLSEXT_KEYNAME_LENGTH, + ctx, ssl_hmac_get0_HMAC_CTX(hctx), 0); + } #endif if (rv < 0) { ret = SSL_TICKET_FATAL_ERR_OTHER; @@ -2300,24 +2319,32 @@ SSL_TICKET_STATUS tls_decrypt_ticket(SSL_CONNECTION *s, EVP_CIPHER *aes256cbc = NULL; /* Check key name matches */ - if (memcmp(etick, tctx->ext.tick_key_name, - TLSEXT_KEYNAME_LENGTH) != 0) { - ret = SSL_TICKET_NO_DECRYPT; - goto end; + if (CRYPTO_THREAD_read_lock(tctx->cnf->cnf_lock)) { + if (memcmp(etick, tctx->cnf->ext.tick_key_name, + TLSEXT_KEYNAME_LENGTH) != 0) { + CRYPTO_THREAD_unlock(tctx->cnf->cnf_lock); + ret = SSL_TICKET_NO_DECRYPT; + goto end; + } + CRYPTO_THREAD_unlock(tctx->cnf->cnf_lock); } aes256cbc = EVP_CIPHER_fetch(sctx->libctx, "AES-256-CBC", sctx->propq); - if (aes256cbc == NULL - || ssl_hmac_init(hctx, tctx->ext.secure->tick_hmac_key, - sizeof(tctx->ext.secure->tick_hmac_key), - "SHA256") <= 0 - || EVP_DecryptInit_ex(ctx, aes256cbc, NULL, - tctx->ext.secure->tick_aes_key, - etick + TLSEXT_KEYNAME_LENGTH) <= 0) { - EVP_CIPHER_free(aes256cbc); - ret = SSL_TICKET_FATAL_ERR_OTHER; - goto end; + if (CRYPTO_THREAD_read_lock(tctx->cnf->cnf_lock)) { + if (aes256cbc == NULL + || ssl_hmac_init(hctx, tctx->cnf->ext.secure->tick_hmac_key, + sizeof(tctx->cnf->ext.secure->tick_hmac_key), + "SHA256") <= 0 + || EVP_DecryptInit_ex(ctx, aes256cbc, NULL, + tctx->cnf->ext.secure->tick_aes_key, + etick + TLSEXT_KEYNAME_LENGTH) <= 0) { + CRYPTO_THREAD_unlock(tctx->cnf->cnf_lock); + EVP_CIPHER_free(aes256cbc); + ret = SSL_TICKET_FATAL_ERR_OTHER; + goto end; + } + CRYPTO_THREAD_unlock(tctx->cnf->cnf_lock); } EVP_CIPHER_free(aes256cbc); if (SSL_CONNECTION_IS_TLS13(s)) @@ -2417,53 +2444,58 @@ SSL_TICKET_STATUS tls_decrypt_ticket(SSL_CONNECTION *s, * detected above. The callback is responsible for checking |ret| before it * performs any action */ - if (s->session_ctx->decrypt_ticket_cb != NULL - && (ret == SSL_TICKET_EMPTY - || ret == SSL_TICKET_NO_DECRYPT - || ret == SSL_TICKET_SUCCESS - || ret == SSL_TICKET_SUCCESS_RENEW)) { - size_t keyname_len = eticklen; - int retcb; - - if (keyname_len > TLSEXT_KEYNAME_LENGTH) - keyname_len = TLSEXT_KEYNAME_LENGTH; - retcb = s->session_ctx->decrypt_ticket_cb(SSL_CONNECTION_GET_SSL(s), - sess, etick, keyname_len, - ret, - s->session_ctx->ticket_cb_data); - switch (retcb) { - case SSL_TICKET_RETURN_ABORT: - ret = SSL_TICKET_FATAL_ERR_OTHER; - break; + if (CRYPTO_THREAD_read_lock(s->session_ctx->cnf->cnf_lock)) { + if (s->session_ctx->cnf->decrypt_ticket_cb != NULL + && (ret == SSL_TICKET_EMPTY + || ret == SSL_TICKET_NO_DECRYPT + || ret == SSL_TICKET_SUCCESS + || ret == SSL_TICKET_SUCCESS_RENEW)) { + size_t keyname_len = eticklen; + int retcb; + + if (keyname_len > TLSEXT_KEYNAME_LENGTH) + keyname_len = TLSEXT_KEYNAME_LENGTH; + retcb = s->session_ctx->cnf->decrypt_ticket_cb(SSL_CONNECTION_GET_SSL(s), + sess, etick, keyname_len, + ret, + s->session_ctx->cnf->ticket_cb_data); + CRYPTO_THREAD_unlock(s->session_ctx->cnf->cnf_lock); + switch (retcb) { + case SSL_TICKET_RETURN_ABORT: + ret = SSL_TICKET_FATAL_ERR_OTHER; + break; - case SSL_TICKET_RETURN_IGNORE: - ret = SSL_TICKET_NONE; - SSL_SESSION_free(sess); - sess = NULL; - break; + case SSL_TICKET_RETURN_IGNORE: + ret = SSL_TICKET_NONE; + SSL_SESSION_free(sess); + sess = NULL; + break; - case SSL_TICKET_RETURN_IGNORE_RENEW: - if (ret != SSL_TICKET_EMPTY && ret != SSL_TICKET_NO_DECRYPT) - ret = SSL_TICKET_NO_DECRYPT; - /* else the value of |ret| will already do the right thing */ - SSL_SESSION_free(sess); - sess = NULL; - break; + case SSL_TICKET_RETURN_IGNORE_RENEW: + if (ret != SSL_TICKET_EMPTY && ret != SSL_TICKET_NO_DECRYPT) + ret = SSL_TICKET_NO_DECRYPT; + /* else the value of |ret| will already do the right thing */ + SSL_SESSION_free(sess); + sess = NULL; + break; - case SSL_TICKET_RETURN_USE: - case SSL_TICKET_RETURN_USE_RENEW: - if (ret != SSL_TICKET_SUCCESS - && ret != SSL_TICKET_SUCCESS_RENEW) - ret = SSL_TICKET_FATAL_ERR_OTHER; - else if (retcb == SSL_TICKET_RETURN_USE) - ret = SSL_TICKET_SUCCESS; - else - ret = SSL_TICKET_SUCCESS_RENEW; - break; + case SSL_TICKET_RETURN_USE: + case SSL_TICKET_RETURN_USE_RENEW: + if (ret != SSL_TICKET_SUCCESS + && ret != SSL_TICKET_SUCCESS_RENEW) + ret = SSL_TICKET_FATAL_ERR_OTHER; + else if (retcb == SSL_TICKET_RETURN_USE) + ret = SSL_TICKET_SUCCESS; + else + ret = SSL_TICKET_SUCCESS_RENEW; + break; - default: - ret = SSL_TICKET_FATAL_ERR_OTHER; + default: + ret = SSL_TICKET_FATAL_ERR_OTHER; + } } + else + CRYPTO_THREAD_unlock(s->session_ctx->cnf->cnf_lock); } if (s->ext.session_secret_cb == NULL || SSL_CONNECTION_IS_TLS13(s)) { @@ -3849,7 +3881,11 @@ int SSL_CTX_set_tlsext_max_fragment_length(SSL_CTX *ctx, uint8_t mode) return 0; } - ctx->ext.max_fragment_len_mode = mode; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->ext.max_fragment_len_mode = mode; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } + return 1; } @@ -3887,11 +3923,15 @@ SSL_HMAC *ssl_hmac_new(const SSL_CTX *ctx) if (ret == NULL) return NULL; #ifndef OPENSSL_NO_DEPRECATED_3_0 - if (ctx->ext.ticket_key_evp_cb == NULL - && ctx->ext.ticket_key_cb != NULL) { - if (!ssl_hmac_old_new(ret)) - goto err; - return ret; + if (CRYPTO_THREAD_read_lock(ctx->cnf->cnf_lock)) { + if (ctx->cnf->ext.ticket_key_evp_cb == NULL + && ctx->cnf->ext.ticket_key_cb != NULL) { + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + if (!ssl_hmac_old_new(ret)) + goto err; + return ret; + } + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); } #endif mac = EVP_MAC_fetch(ctx->libctx, "HMAC", ctx->propq); diff --git a/ssl/tls_depr.c b/ssl/tls_depr.c index 85ed9f25f92959..603fe7ec8f8fde 100644 --- a/ssl/tls_depr.c +++ b/ssl/tls_depr.c @@ -68,8 +68,14 @@ int tls_engine_load_ssl_client_cert(SSL_CONNECTION *s, X509 **px509, EVP_PKEY **ppkey) { SSL *ssl = SSL_CONNECTION_GET_SSL(s); + ENGINE *engine = NULL; - return ENGINE_load_ssl_client_cert(SSL_CONNECTION_GET_CTX(s)->client_cert_engine, + if (CRYPTO_THREAD_read_lock(SSL_CONNECTION_GET_CTX(s)->cnf->cnf_lock)) { + engine = SSL_CONNECTION_GET_CTX(s)->cnf->client_cert_engine; + CRYPTO_THREAD_unlock(SSL_CONNECTION_GET_CTX(s)->cnf->cnf_lock); + } + + return ENGINE_load_ssl_client_cert(engine, ssl, SSL_get_client_CA_list(ssl), px509, ppkey, NULL, NULL, NULL); @@ -88,7 +94,10 @@ int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e) ENGINE_finish(e); return 0; } - ctx->client_cert_engine = e; + if (CRYPTO_THREAD_write_lock(ctx->cnf->cnf_lock)) { + ctx->cnf->client_cert_engine = e; + CRYPTO_THREAD_unlock(ctx->cnf->cnf_lock); + } return 1; } #endif diff --git a/test/sslapitest.c b/test/sslapitest.c index 021b50e8e56b8c..9700a9feb70f6f 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -9718,6 +9718,55 @@ static int test_pluggable_signature(int idx) #endif #ifndef OPENSSL_NO_TLS1_2 +static int test_ssl_ctx_dup(void) +{ + SSL_CTX *cctx = NULL, *sctx = NULL; + SSL_CTX *cctx_dup = NULL, *sctx_dup = NULL; + SSL *clientssl = NULL, *serverssl = NULL; + int testresult = 0; + + if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), + TLS_client_method(), + 0, + 0, + &sctx, &cctx, cert, privkey))) + goto end; + + if (!TEST_ptr(cctx_dup = SSL_CTX_dup(libctx, cctx, NULL, TLS_client_method()))) + goto end; + + if (!TEST_ptr(sctx_dup = SSL_CTX_dup(libctx, sctx, NULL, TLS_server_method()))) + goto end; + + if (!TEST_true(create_ssl_objects(sctx_dup, cctx_dup, &serverssl, &clientssl, + NULL, NULL))) + goto end; + + if (!TEST_ptr(clientssl) + || !TEST_ptr_ne(sctx, sctx_dup) + || !TEST_ptr_ne(cctx, cctx_dup)) + goto end; + + if (!TEST_true(SSL_set_min_proto_version(clientssl, TLS1_2_VERSION)) + || !TEST_true(SSL_set_max_proto_version(clientssl, TLS1_2_VERSION))) + goto end; + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) + goto end; + + testresult = 1; + +end: + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + SSL_CTX_free(sctx_dup); + SSL_CTX_free(cctx_dup); + + return testresult; +} + static int test_ssl_dup(void) { SSL_CTX *cctx = NULL, *sctx = NULL; @@ -11635,6 +11684,7 @@ int setup_tests(void) ADD_ALL_TESTS(test_pluggable_signature, 4); #endif #ifndef OPENSSL_NO_TLS1_2 + ADD_TEST(test_ssl_ctx_dup); ADD_TEST(test_ssl_dup); # ifndef OPENSSL_NO_DH ADD_ALL_TESTS(test_set_tmp_dh, 11); diff --git a/util/libssl.num b/util/libssl.num index 22b31fb012a87c..251c349e80eee5 100644 --- a/util/libssl.num +++ b/util/libssl.num @@ -577,3 +577,4 @@ SSL_handle_events 577 3_2_0 EXIST::FUNCTION: SSL_get_event_timeout 578 3_2_0 EXIST::FUNCTION: SSL_get0_group_name 579 3_2_0 EXIST::FUNCTION: SSL_is_stream_local 580 3_2_0 EXIST::FUNCTION: +SSL_CTX_dup 581 3_2_0 EXIST::FUNCTION: