diff options
Diffstat (limited to 'src/ssl/ssl_lib.c')
-rw-r--r-- | src/ssl/ssl_lib.c | 927 |
1 files changed, 356 insertions, 571 deletions
diff --git a/src/ssl/ssl_lib.c b/src/ssl/ssl_lib.c index 35eb1ec..6c8e2c9 100644 --- a/src/ssl/ssl_lib.c +++ b/src/ssl/ssl_lib.c @@ -138,19 +138,22 @@ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR * OTHERWISE. */ -#include <stdio.h> #include <assert.h> +#include <stdio.h> +#include <string.h> #include <openssl/bytestring.h> #include <openssl/dh.h> -#include <openssl/engine.h> +#include <openssl/err.h> #include <openssl/lhash.h> #include <openssl/mem.h> #include <openssl/obj.h> #include <openssl/rand.h> #include <openssl/x509v3.h> -#include "ssl_locl.h" +#include "internal.h" +#include "../crypto/internal.h" + /* Some error codes are special. Ensure the make_errors.go script never * regresses this. */ @@ -158,6 +161,12 @@ OPENSSL_COMPILE_ASSERT(SSL_R_TLSV1_ALERT_NO_RENEGOTIATION == SSL_AD_NO_RENEGOTIATION + SSL_AD_REASON_OFFSET, ssl_alert_reason_code_mismatch); +/* kMaxHandshakeSize is the maximum size, in bytes, of a handshake message. */ +static const size_t kMaxHandshakeSize = (1u << 24) - 1; + +static CRYPTO_EX_DATA_CLASS g_ex_data_class_ssl = CRYPTO_EX_DATA_CLASS_INIT; +static CRYPTO_EX_DATA_CLASS g_ex_data_class_ssl_ctx = CRYPTO_EX_DATA_CLASS_INIT; + int SSL_clear(SSL *s) { if (s->method == NULL) { OPENSSL_PUT_ERROR(SSL, SSL_clear, SSL_R_NO_METHOD_SPECIFIED); @@ -199,21 +208,17 @@ int SSL_clear(SSL *s) { s->rwstate = SSL_NOTHING; s->rstate = SSL_ST_READ_HEADER; - if (s->init_buf != NULL) { - BUF_MEM_free(s->init_buf); - s->init_buf = NULL; - } + BUF_MEM_free(s->init_buf); + s->init_buf = NULL; s->packet = NULL; s->packet_length = 0; ssl_clear_cipher_ctx(s); - if (s->next_proto_negotiated) { - OPENSSL_free(s->next_proto_negotiated); - s->next_proto_negotiated = NULL; - s->next_proto_negotiated_len = 0; - } + OPENSSL_free(s->next_proto_negotiated); + s->next_proto_negotiated = NULL; + s->next_proto_negotiated_len = 0; /* The s->d1->mtu is simultaneously configuration (preserved across * clear) and connection-specific state (gets reset). @@ -265,21 +270,9 @@ SSL *SSL_new(SSL_CTX *ctx) { s->mode = ctx->mode; s->max_cert_list = ctx->max_cert_list; - if (ctx->cert != NULL) { - /* 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 err; - } - } else { - s->cert = NULL; /* Cannot really happen (see SSL_CTX_new) */ + s->cert = ssl_cert_dup(ctx->cert); + if (s->cert == NULL) { + goto err; } s->read_ahead = ctx->read_ahead; @@ -302,8 +295,6 @@ SSL *SSL_new(SSL_CTX *ctx) { CRYPTO_add(&ctx->references, 1, CRYPTO_LOCK_SSL_CTX); s->ctx = ctx; - s->tlsext_debug_cb = 0; - s->tlsext_debug_arg = NULL; s->tlsext_ticket_expected = 0; CRYPTO_add(&ctx->references, 1, CRYPTO_LOCK_SSL_CTX); s->initial_ctx = ctx; @@ -345,12 +336,10 @@ SSL *SSL_new(SSL_CTX *ctx) { s->enc_method = ssl3_get_enc_method(s->version); assert(s->enc_method != NULL); - s->references = 1; - s->rwstate = SSL_NOTHING; s->rstate = SSL_ST_READ_HEADER; - CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data); + CRYPTO_new_ex_data(&g_ex_data_class_ssl, s, &s->ex_data); s->psk_identity_hint = NULL; if (ctx->psk_identity_hint) { @@ -364,7 +353,8 @@ SSL *SSL_new(SSL_CTX *ctx) { s->tlsext_channel_id_enabled = ctx->tlsext_channel_id_enabled; if (ctx->tlsext_channel_id_private) { - s->tlsext_channel_id_private = EVP_PKEY_dup(ctx->tlsext_channel_id_private); + s->tlsext_channel_id_private = + EVP_PKEY_up_ref(ctx->tlsext_channel_id_private); } s->signed_cert_timestamps_enabled = s->ctx->signed_cert_timestamps_enabled; @@ -373,9 +363,7 @@ SSL *SSL_new(SSL_CTX *ctx) { return s; err: - if (s != NULL) { - SSL_free(s); - } + SSL_free(s); OPENSSL_PUT_ERROR(SSL, SSL_new, ERR_R_MALLOC_FAILURE); return NULL; @@ -415,9 +403,7 @@ int SSL_CTX_set_generate_session_id(SSL_CTX *ctx, GEN_SESSION_CB cb) { } int SSL_set_generate_session_id(SSL *ssl, GEN_SESSION_CB cb) { - CRYPTO_w_lock(CRYPTO_LOCK_SSL); ssl->generate_session_id = cb; - CRYPTO_w_unlock(CRYPTO_LOCK_SSL); return 1; } @@ -470,6 +456,9 @@ int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm) { void ssl_cipher_preference_list_free( struct ssl_cipher_preference_list_st *cipher_list) { + if (cipher_list == NULL) { + return; + } sk_SSL_CIPHER_free(cipher_list->ciphers); OPENSSL_free(cipher_list->in_group_flags); OPENSSL_free(cipher_list); @@ -499,17 +488,12 @@ struct ssl_cipher_preference_list_st *ssl_cipher_preference_list_dup( return ret; err: - if (ret && ret->ciphers) { - sk_SSL_CIPHER_free(ret->ciphers); - } - if (ret) { - OPENSSL_free(ret); - } + ssl_cipher_preference_list_free(ret); return NULL; } struct ssl_cipher_preference_list_st *ssl_cipher_preference_list_from_ciphers( - STACK_OF(SSL_CIPHER) * ciphers) { + STACK_OF(SSL_CIPHER) *ciphers) { struct ssl_cipher_preference_list_st *ret = NULL; size_t n = sk_SSL_CIPHER_num(ciphers); @@ -531,12 +515,7 @@ struct ssl_cipher_preference_list_st *ssl_cipher_preference_list_from_ciphers( return ret; err: - if (ret && ret->ciphers) { - sk_SSL_CIPHER_free(ret->ciphers); - } - if (ret) { - OPENSSL_free(ret); - } + ssl_cipher_preference_list_free(ret); return NULL; } @@ -547,22 +526,13 @@ X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl) { return ssl->param; } void SSL_certs_clear(SSL *s) { ssl_cert_clear_certs(s->cert); } void SSL_free(SSL *s) { - int i; - if (s == NULL) { return; } - i = CRYPTO_add(&s->references, -1, CRYPTO_LOCK_SSL); - if (i > 0) { - return; - } - - if (s->param) { - X509_VERIFY_PARAM_free(s->param); - } + X509_VERIFY_PARAM_free(s->param); - CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data); + CRYPTO_free_ex_data(&g_ex_data_class_ssl, s, &s->ex_data); if (s->bbio != NULL) { /* If the buffering BIO is in place, pop it off */ @@ -573,74 +543,40 @@ void SSL_free(SSL *s) { s->bbio = NULL; } - if (s->rbio != NULL) { - BIO_free_all(s->rbio); - } - - if (s->wbio != NULL && s->wbio != s->rbio) { + int free_wbio = s->wbio != s->rbio; + BIO_free_all(s->rbio); + if (free_wbio) { BIO_free_all(s->wbio); } - if (s->init_buf != NULL) { - BUF_MEM_free(s->init_buf); - } + BUF_MEM_free(s->init_buf); /* add extra stuff */ - if (s->cipher_list != NULL) { - ssl_cipher_preference_list_free(s->cipher_list); - } - if (s->cipher_list_by_id != NULL) { - sk_SSL_CIPHER_free(s->cipher_list_by_id); - } + ssl_cipher_preference_list_free(s->cipher_list); + sk_SSL_CIPHER_free(s->cipher_list_by_id); - if (s->session != NULL) { - ssl_clear_bad_session(s); - SSL_SESSION_free(s->session); - } + ssl_clear_bad_session(s); + SSL_SESSION_free(s->session); ssl_clear_cipher_ctx(s); - if (s->cert != NULL) { - ssl_cert_free(s->cert); - } + ssl_cert_free(s->cert); - if (s->tlsext_hostname) { - OPENSSL_free(s->tlsext_hostname); - } - if (s->initial_ctx) { - SSL_CTX_free(s->initial_ctx); - } - if (s->tlsext_ecpointformatlist) { - OPENSSL_free(s->tlsext_ecpointformatlist); - } - if (s->tlsext_ellipticcurvelist) { - OPENSSL_free(s->tlsext_ellipticcurvelist); - } - if (s->alpn_client_proto_list) { - OPENSSL_free(s->alpn_client_proto_list); - } - if (s->tlsext_channel_id_private) { - EVP_PKEY_free(s->tlsext_channel_id_private); - } - if (s->psk_identity_hint) { - OPENSSL_free(s->psk_identity_hint); - } - if (s->client_CA != NULL) { - sk_X509_NAME_pop_free(s->client_CA, X509_NAME_free); - } - if (s->next_proto_negotiated) { - OPENSSL_free(s->next_proto_negotiated); - } - if (s->srtp_profiles) { - sk_SRTP_PROTECTION_PROFILE_free(s->srtp_profiles); - } + OPENSSL_free(s->tlsext_hostname); + SSL_CTX_free(s->initial_ctx); + OPENSSL_free(s->tlsext_ecpointformatlist); + OPENSSL_free(s->tlsext_ellipticcurvelist); + OPENSSL_free(s->alpn_client_proto_list); + EVP_PKEY_free(s->tlsext_channel_id_private); + OPENSSL_free(s->psk_identity_hint); + sk_X509_NAME_pop_free(s->client_CA, X509_NAME_free); + OPENSSL_free(s->next_proto_negotiated); + sk_SRTP_PROTECTION_PROFILE_free(s->srtp_profiles); if (s->method != NULL) { s->method->ssl_free(s); } - if (s->ctx) { - SSL_CTX_free(s->ctx); - } + SSL_CTX_free(s->ctx); OPENSSL_free(s); } @@ -654,10 +590,10 @@ void SSL_set_bio(SSL *s, BIO *rbio, BIO *wbio) { } } - if (s->rbio != NULL && s->rbio != rbio) { + if (s->rbio != rbio) { BIO_free_all(s->rbio); } - if (s->wbio != NULL && s->wbio != wbio && s->rbio != s->wbio) { + if (s->wbio != wbio && s->rbio != s->wbio) { BIO_free_all(s->wbio); } s->rbio = rbio; @@ -822,10 +758,14 @@ void SSL_set_verify_depth(SSL *s, int depth) { X509_VERIFY_PARAM_set_depth(s->param, depth); } -void SSL_set_read_ahead(SSL *s, int yes) { s->read_ahead = yes; } +int SSL_CTX_get_read_ahead(const SSL_CTX *ctx) { return ctx->read_ahead; } int SSL_get_read_ahead(const SSL *s) { return s->read_ahead; } +void SSL_CTX_set_read_ahead(SSL_CTX *ctx, int yes) { ctx->read_ahead = !!yes; } + +void SSL_set_read_ahead(SSL *s, int yes) { s->read_ahead = !!yes; } + int SSL_pending(const SSL *s) { /* SSL_pending cannot work properly if read-ahead is enabled * (SSL_[CTX_]ctrl(..., SSL_CTRL_SET_READ_AHEAD, 1, NULL)), and it is @@ -851,8 +791,8 @@ X509 *SSL_get_peer_certificate(const SSL *s) { return X509_up_ref(r); } -STACK_OF(X509) * SSL_get_peer_cert_chain(const SSL *s) { - STACK_OF(X509) * r; +STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s) { + STACK_OF(X509) *r; if (s == NULL || s->session == NULL || s->session->sess_cert == NULL) { r = NULL; @@ -919,7 +859,7 @@ int SSL_accept(SSL *s) { } if (s->handshake_func != s->method->ssl_accept) { - OPENSSL_PUT_ERROR(SSL, SSL_connect, ERR_R_INTERNAL_ERROR); + OPENSSL_PUT_ERROR(SSL, SSL_accept, ERR_R_INTERNAL_ERROR); return -1; } @@ -1005,20 +945,17 @@ int SSL_shutdown(SSL *s) { } int SSL_renegotiate(SSL *s) { - if (s->renegotiate == 0) { - s->renegotiate = 1; + if (SSL_IS_DTLS(s)) { + /* Renegotiation is not supported for DTLS. */ + OPENSSL_PUT_ERROR(SSL, SSL_renegotiate, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; } - s->new_session = 1; - return s->method->ssl_renegotiate(s); -} - -int SSL_renegotiate_abbreviated(SSL *s) { if (s->renegotiate == 0) { s->renegotiate = 1; } - s->new_session = 0; + s->new_session = 1; return s->method->ssl_renegotiate(s); } @@ -1028,221 +965,140 @@ int SSL_renegotiate_pending(SSL *s) { return s->renegotiate != 0; } -long SSL_ctrl(SSL *s, int cmd, long larg, void *parg) { - long l; - - switch (cmd) { - case SSL_CTRL_GET_READ_AHEAD: - return s->read_ahead; - - case SSL_CTRL_SET_READ_AHEAD: - l = s->read_ahead; - s->read_ahead = larg; - return l; - - case SSL_CTRL_SET_MSG_CALLBACK_ARG: - s->msg_callback_arg = parg; - return 1; - - case SSL_CTRL_OPTIONS: - return s->options |= larg; +uint32_t SSL_CTX_set_options(SSL_CTX *ctx, uint32_t options) { + ctx->options |= options; + return ctx->options; +} - case SSL_CTRL_CLEAR_OPTIONS: - return s->options &= ~larg; +uint32_t SSL_set_options(SSL *ssl, uint32_t options) { + ssl->options |= options; + return ssl->options; +} - case SSL_CTRL_MODE: - return s->mode |= larg; +uint32_t SSL_CTX_clear_options(SSL_CTX *ctx, uint32_t options) { + ctx->options &= ~options; + return ctx->options; +} - case SSL_CTRL_CLEAR_MODE: - return s->mode &= ~larg; +uint32_t SSL_clear_options(SSL *ssl, uint32_t options) { + ssl->options &= ~options; + return ssl->options; +} - case SSL_CTRL_GET_MAX_CERT_LIST: - return s->max_cert_list; +uint32_t SSL_CTX_get_options(const SSL_CTX *ctx) { return ctx->options; } - case SSL_CTRL_SET_MAX_CERT_LIST: - l = s->max_cert_list; - s->max_cert_list = larg; - return l; +uint32_t SSL_get_options(const SSL *ssl) { return ssl->options; } - case SSL_CTRL_SET_MTU: - if (larg < (long)dtls1_min_mtu()) { - return 0; - } - if (SSL_IS_DTLS(s)) { - s->d1->mtu = larg; - return larg; - } - return 0; +uint32_t SSL_CTX_set_mode(SSL_CTX *ctx, uint32_t mode) { + ctx->mode |= mode; + return ctx->mode; +} - case SSL_CTRL_SET_MAX_SEND_FRAGMENT: - if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH) { - return 0; - } - s->max_send_fragment = larg; - return 1; +uint32_t SSL_set_mode(SSL *ssl, uint32_t mode) { + ssl->mode |= mode; + return ssl->mode; +} - case SSL_CTRL_GET_RI_SUPPORT: - if (s->s3) { - return s->s3->send_connection_binding; - } - return 0; +uint32_t SSL_CTX_clear_mode(SSL_CTX *ctx, uint32_t mode) { + ctx->mode &= ~mode; + return ctx->mode; +} - case SSL_CTRL_CERT_FLAGS: - return s->cert->cert_flags |= larg; +uint32_t SSL_clear_mode(SSL *ssl, uint32_t mode) { + ssl->mode &= ~mode; + return ssl->mode; +} - case SSL_CTRL_CLEAR_CERT_FLAGS: - return s->cert->cert_flags &= ~larg; +uint32_t SSL_CTX_get_mode(const SSL_CTX *ctx) { return ctx->mode; } - case SSL_CTRL_GET_RAW_CIPHERLIST: - if (parg) { - if (s->cert->ciphers_raw == NULL) { - return 0; - } - *(uint8_t **)parg = s->cert->ciphers_raw; - return (int)s->cert->ciphers_rawlen; - } +uint32_t SSL_get_mode(const SSL *ssl) { return ssl->mode; } - /* Passing a NULL |parg| returns the size of a single - * cipher suite value. */ - return 2; +size_t SSL_CTX_get_max_cert_list(const SSL_CTX *ctx) { + return ctx->max_cert_list; +} - default: - return s->method->ssl_ctrl(s, cmd, larg, parg); +void SSL_CTX_set_max_cert_list(SSL_CTX *ctx, size_t max_cert_list) { + if (max_cert_list > kMaxHandshakeSize) { + max_cert_list = kMaxHandshakeSize; } + ctx->max_cert_list = (uint32_t)max_cert_list; } -long SSL_callback_ctrl(SSL *s, int cmd, void (*fp)(void)) { - switch (cmd) { - case SSL_CTRL_SET_MSG_CALLBACK: - s->msg_callback = - (void (*)(int write_p, int version, int content_type, const void *buf, - size_t len, SSL *ssl, void *arg))(fp); - return 1; +size_t SSL_get_max_cert_list(const SSL *ssl) { + return ssl->max_cert_list; +} - default: - return s->method->ssl_callback_ctrl(s, cmd, fp); +void SSL_set_max_cert_list(SSL *ssl, size_t max_cert_list) { + if (max_cert_list > kMaxHandshakeSize) { + max_cert_list = kMaxHandshakeSize; } + ssl->max_cert_list = (uint32_t)max_cert_list; } -LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx) { return ctx->sessions; } - -long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) { - long l; - - switch (cmd) { - case SSL_CTRL_GET_READ_AHEAD: - return ctx->read_ahead; - - case SSL_CTRL_SET_READ_AHEAD: - l = ctx->read_ahead; - ctx->read_ahead = larg; - return l; - - case SSL_CTRL_SET_MSG_CALLBACK_ARG: - ctx->msg_callback_arg = parg; - return 1; - - case SSL_CTRL_GET_MAX_CERT_LIST: - return ctx->max_cert_list; - - case SSL_CTRL_SET_MAX_CERT_LIST: - l = ctx->max_cert_list; - ctx->max_cert_list = larg; - return l; - - case SSL_CTRL_SET_SESS_CACHE_SIZE: - l = ctx->session_cache_size; - ctx->session_cache_size = larg; - return l; - - case SSL_CTRL_GET_SESS_CACHE_SIZE: - return ctx->session_cache_size; - - case SSL_CTRL_SET_SESS_CACHE_MODE: - l = ctx->session_cache_mode; - ctx->session_cache_mode = larg; - return l; - - case SSL_CTRL_GET_SESS_CACHE_MODE: - return ctx->session_cache_mode; - - case SSL_CTRL_SESS_NUMBER: - return lh_SSL_SESSION_num_items(ctx->sessions); - - case SSL_CTRL_SESS_CONNECT: - return ctx->stats.sess_connect; - - case SSL_CTRL_SESS_CONNECT_GOOD: - return ctx->stats.sess_connect_good; - - case SSL_CTRL_SESS_CONNECT_RENEGOTIATE: - return ctx->stats.sess_connect_renegotiate; - - case SSL_CTRL_SESS_ACCEPT: - return ctx->stats.sess_accept; - - case SSL_CTRL_SESS_ACCEPT_GOOD: - return ctx->stats.sess_accept_good; - - case SSL_CTRL_SESS_ACCEPT_RENEGOTIATE: - return ctx->stats.sess_accept_renegotiate; - - case SSL_CTRL_SESS_HIT: - return ctx->stats.sess_hit; - - case SSL_CTRL_SESS_CB_HIT: - return ctx->stats.sess_cb_hit; - - case SSL_CTRL_SESS_MISSES: - return ctx->stats.sess_miss; - - case SSL_CTRL_SESS_TIMEOUTS: - return ctx->stats.sess_timeout; +void SSL_CTX_set_max_send_fragment(SSL_CTX *ctx, size_t max_send_fragment) { + if (max_send_fragment < 512) { + max_send_fragment = 512; + } + if (max_send_fragment > SSL3_RT_MAX_PLAIN_LENGTH) { + max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH; + } + ctx->max_send_fragment = (uint16_t)max_send_fragment; +} - case SSL_CTRL_SESS_CACHE_FULL: - return ctx->stats.sess_cache_full; +void SSL_set_max_send_fragment(SSL *ssl, size_t max_send_fragment) { + if (max_send_fragment < 512) { + max_send_fragment = 512; + } + if (max_send_fragment > SSL3_RT_MAX_PLAIN_LENGTH) { + max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH; + } + ssl->max_send_fragment = (uint16_t)max_send_fragment; +} - case SSL_CTRL_OPTIONS: - return ctx->options |= larg; +int SSL_set_mtu(SSL *ssl, unsigned mtu) { + if (!SSL_IS_DTLS(ssl) || mtu < dtls1_min_mtu()) { + return 0; + } + ssl->d1->mtu = mtu; + return 1; +} - case SSL_CTRL_CLEAR_OPTIONS: - return ctx->options &= ~larg; +int SSL_get_secure_renegotiation_support(const SSL *ssl) { + return ssl->s3->send_connection_binding; +} - case SSL_CTRL_MODE: - return ctx->mode |= larg; +long SSL_ctrl(SSL *s, int cmd, long larg, void *parg) { + return s->method->ssl_ctrl(s, cmd, larg, parg); +} - case SSL_CTRL_CLEAR_MODE: - return ctx->mode &= ~larg; +LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx) { return ctx->sessions; } - case SSL_CTRL_SET_MAX_SEND_FRAGMENT: - if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH) { - return 0; - } - ctx->max_send_fragment = larg; - return 1; +size_t SSL_CTX_sess_number(const SSL_CTX *ctx) { + return lh_SSL_SESSION_num_items(ctx->sessions); +} - case SSL_CTRL_CERT_FLAGS: - return ctx->cert->cert_flags |= larg; +unsigned long SSL_CTX_sess_set_cache_size(SSL_CTX *ctx, unsigned long size) { + unsigned long ret = ctx->session_cache_size; + ctx->session_cache_size = size; + return ret; +} - case SSL_CTRL_CLEAR_CERT_FLAGS: - return ctx->cert->cert_flags &= ~larg; +unsigned long SSL_CTX_sess_get_cache_size(const SSL_CTX *ctx) { + return ctx->session_cache_size; +} - default: - return ctx->method->ssl_ctx_ctrl(ctx, cmd, larg, parg); - } +int SSL_CTX_set_session_cache_mode(SSL_CTX *ctx, int mode) { + int ret = ctx->session_cache_mode; + ctx->session_cache_mode = mode; + return ret; } -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); - return 1; +int SSL_CTX_get_session_cache_mode(const SSL_CTX *ctx) { + return ctx->session_cache_mode; +} - default: - return ctx->method->ssl_ctx_callback_ctrl(ctx, cmd, fp); - } +long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) { + return ctx->method->ssl_ctx_ctrl(ctx, cmd, larg, parg); } int ssl_cipher_id_cmp(const void *in_a, const void *in_b) { @@ -1275,7 +1131,7 @@ int ssl_cipher_ptr_id_cmp(const SSL_CIPHER **ap, const SSL_CIPHER **bp) { /* return a STACK of the ciphers available for the SSL and in order of * preference */ -STACK_OF(SSL_CIPHER) * SSL_get_ciphers(const SSL *s) { +STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s) { if (s == NULL) { return NULL; } @@ -1298,7 +1154,7 @@ STACK_OF(SSL_CIPHER) * SSL_get_ciphers(const SSL *s) { /* return a STACK of the ciphers available for the SSL and in order of * algorithm id */ -STACK_OF(SSL_CIPHER) * ssl_get_ciphers_by_id(SSL *s) { +STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s) { if (s == NULL) { return NULL; } @@ -1317,7 +1173,7 @@ STACK_OF(SSL_CIPHER) * ssl_get_ciphers_by_id(SSL *s) { /* The old interface to get the same thing as SSL_get_ciphers() */ const char *SSL_get_cipher_list(const SSL *s, int n) { const SSL_CIPHER *c; - STACK_OF(SSL_CIPHER) * sk; + STACK_OF(SSL_CIPHER) *sk; if (s == NULL) { return NULL; @@ -1341,7 +1197,7 @@ int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) { STACK_OF(SSL_CIPHER) *sk; sk = ssl_create_cipher_list(ctx->method, &ctx->cipher_list, - &ctx->cipher_list_by_id, str, ctx->cert); + &ctx->cipher_list_by_id, str); /* 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 string * specifies a cipher which has been disabled). This is not an error as far @@ -1360,8 +1216,7 @@ int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) { int SSL_CTX_set_cipher_list_tls11(SSL_CTX *ctx, const char *str) { STACK_OF(SSL_CIPHER) *sk; - sk = ssl_create_cipher_list(ctx->method, &ctx->cipher_list_tls11, NULL, str, - ctx->cert); + sk = ssl_create_cipher_list(ctx->method, &ctx->cipher_list_tls11, NULL, str); if (sk == NULL) { return 0; } else if (sk_SSL_CIPHER_num(sk) == 0) { @@ -1378,7 +1233,7 @@ int SSL_set_cipher_list(SSL *s, const char *str) { STACK_OF(SSL_CIPHER) *sk; sk = ssl_create_cipher_list(s->ctx->method, &s->cipher_list, - &s->cipher_list_by_id, str, s->cert); + &s->cipher_list_by_id, str); /* see comment in SSL_CTX_set_cipher_list */ if (sk == NULL) { @@ -1435,7 +1290,7 @@ int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, uint8_t *p) { STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, const CBS *cbs) { CBS cipher_suites = *cbs; const SSL_CIPHER *c; - STACK_OF(SSL_CIPHER) * sk; + STACK_OF(SSL_CIPHER) *sk; if (s->s3) { s->s3->send_connection_binding = 0; @@ -1453,12 +1308,6 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, const CBS *cbs) { goto err; } - if (!CBS_stow(&cipher_suites, &s->cert->ciphers_raw, - &s->cert->ciphers_rawlen)) { - OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list, ERR_R_MALLOC_FAILURE); - goto err; - } - while (CBS_len(&cipher_suites) > 0) { uint16_t cipher_suite; @@ -1503,9 +1352,7 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, const CBS *cbs) { return sk; err: - if (sk != NULL) { - sk_SSL_CIPHER_free(sk); - } + sk_SSL_CIPHER_free(sk); return NULL; } @@ -1691,17 +1538,9 @@ void SSL_CTX_set_next_proto_select_cb( ctx->next_proto_select_cb_arg = arg; } -/* SSL_CTX_set_alpn_protos sets the ALPN protocol list on |ctx| to |protos|. - * |protos| must be in wire-format (i.e. a series of non-empty, 8-bit - * length-prefixed strings). - * - * Returns 0 on success. */ int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const uint8_t *protos, unsigned protos_len) { - if (ctx->alpn_client_proto_list) { - OPENSSL_free(ctx->alpn_client_proto_list); - } - + OPENSSL_free(ctx->alpn_client_proto_list); ctx->alpn_client_proto_list = BUF_memdup(protos, protos_len); if (!ctx->alpn_client_proto_list) { return 1; @@ -1711,16 +1550,8 @@ int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const uint8_t *protos, return 0; } -/* SSL_set_alpn_protos sets the ALPN protocol list on |ssl| to |protos|. - * |protos| must be in wire-format (i.e. a series of non-empty, 8-bit - * length-prefixed strings). - * - * Returns 0 on success. */ int SSL_set_alpn_protos(SSL *ssl, const uint8_t *protos, unsigned protos_len) { - if (ssl->alpn_client_proto_list) { - OPENSSL_free(ssl->alpn_client_proto_list); - } - + OPENSSL_free(ssl->alpn_client_proto_list); ssl->alpn_client_proto_list = BUF_memdup(protos, protos_len); if (!ssl->alpn_client_proto_list) { return 1; @@ -1759,15 +1590,16 @@ void SSL_get0_alpn_selected(const SSL *ssl, const uint8_t **data, } } -int SSL_export_keying_material(SSL *s, uint8_t *out, size_t olen, - const char *label, size_t llen, const uint8_t *p, - size_t plen, int use_context) { +int SSL_export_keying_material(SSL *s, uint8_t *out, size_t out_len, + const char *label, size_t label_len, + const uint8_t *context, size_t context_len, + int use_context) { if (s->version < TLS1_VERSION) { - return -1; + return 0; } - return s->enc_method->export_keying_material(s, out, olen, label, llen, p, - plen, use_context); + return s->enc_method->export_keying_material( + s, out, out_len, label, label_len, context, context_len, use_context); } static uint32_t ssl_session_hash(const SSL_SESSION *a) { @@ -1833,8 +1665,6 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) { ret->get_session_cb = 0; ret->generate_session_id = 0; - memset((char *)&ret->stats, 0, sizeof(ret->stats)); - ret->references = 1; ret->quiet_shutdown = 0; @@ -1858,8 +1688,6 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) { ret->default_passwd_callback = 0; ret->default_passwd_callback_userdata = NULL; ret->client_cert_cb = 0; - ret->app_gen_cookie_cb = 0; - ret->app_verify_cookie_cb = 0; ret->sessions = lh_SSL_SESSION_new(ssl_session_hash, ssl_session_cmp); if (ret->sessions == NULL) { @@ -1871,8 +1699,7 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) { } ssl_create_cipher_list(ret->method, &ret->cipher_list, - &ret->cipher_list_by_id, SSL_DEFAULT_CIPHER_LIST, - ret->cert); + &ret->cipher_list_by_id, SSL_DEFAULT_CIPHER_LIST); if (ret->cipher_list == NULL || sk_SSL_CIPHER_num(ret->cipher_list->ciphers) <= 0) { OPENSSL_PUT_ERROR(SSL, SSL_CTX_new, SSL_R_LIBRARY_HAS_NO_CIPHERS); @@ -1889,7 +1716,7 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) { goto err; } - CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_CTX, ret, &ret->ex_data); + CRYPTO_new_ex_data(&g_ex_data_class_ssl_ctx, ret, &ret->ex_data); ret->extra_certs = NULL; @@ -1904,9 +1731,6 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) { ret->options |= SSL_OP_NO_TICKET; } - ret->tlsext_status_cb = 0; - ret->tlsext_status_arg = NULL; - ret->next_protos_advertised_cb = 0; ret->next_proto_select_cb = 0; ret->psk_identity_hint = NULL; @@ -1929,27 +1753,17 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) { err: OPENSSL_PUT_ERROR(SSL, SSL_CTX_new, ERR_R_MALLOC_FAILURE); err2: - if (ret != NULL) { - SSL_CTX_free(ret); - } + SSL_CTX_free(ret); return NULL; } -void SSL_CTX_free(SSL_CTX *a) { - int i; - - if (a == NULL) { +void SSL_CTX_free(SSL_CTX *ctx) { + if (ctx == NULL || + CRYPTO_add(&ctx->references, -1, CRYPTO_LOCK_SSL_CTX) > 0) { return; } - i = CRYPTO_add(&a->references, -1, CRYPTO_LOCK_SSL_CTX); - if (i > 0) { - return; - } - - if (a->param) { - X509_VERIFY_PARAM_free(a->param); - } + X509_VERIFY_PARAM_free(ctx->param); /* Free internal session cache. However: the remove_cb() may reference the * ex_data of SSL_CTX, thus the ex_data store can only be removed after the @@ -1957,59 +1771,27 @@ void SSL_CTX_free(SSL_CTX *a) { * the session cache, the most secure solution seems to be: empty (flush) the * cache, then free ex_data, then finally free the cache. (See ticket * [openssl.org #212].) */ - if (a->sessions != NULL) { - SSL_CTX_flush_sessions(a, 0); - } + SSL_CTX_flush_sessions(ctx, 0); - CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_CTX, a, &a->ex_data); + CRYPTO_free_ex_data(&g_ex_data_class_ssl_ctx, ctx, &ctx->ex_data); - if (a->sessions != NULL) { - lh_SSL_SESSION_free(a->sessions); - } - if (a->cert_store != NULL) { - X509_STORE_free(a->cert_store); - } - if (a->cipher_list != NULL) { - ssl_cipher_preference_list_free(a->cipher_list); - } - if (a->cipher_list_by_id != NULL) { - sk_SSL_CIPHER_free(a->cipher_list_by_id); - } - if (a->cipher_list_tls11 != NULL) { - ssl_cipher_preference_list_free(a->cipher_list_tls11); - } - if (a->cert != NULL) { - ssl_cert_free(a->cert); - } - if (a->client_CA != NULL) { - sk_X509_NAME_pop_free(a->client_CA, X509_NAME_free); - } - if (a->extra_certs != NULL) { - sk_X509_pop_free(a->extra_certs, X509_free); - } - if (a->srtp_profiles) { - sk_SRTP_PROTECTION_PROFILE_free(a->srtp_profiles); - } - if (a->psk_identity_hint) { - OPENSSL_free(a->psk_identity_hint); - } - if (a->tlsext_ecpointformatlist) { - OPENSSL_free(a->tlsext_ecpointformatlist); - } - if (a->tlsext_ellipticcurvelist) { - OPENSSL_free(a->tlsext_ellipticcurvelist); - } - if (a->alpn_client_proto_list != NULL) { - OPENSSL_free(a->alpn_client_proto_list); - } - if (a->tlsext_channel_id_private) { - EVP_PKEY_free(a->tlsext_channel_id_private); - } - if (a->keylog_bio) { - BIO_free(a->keylog_bio); - } + lh_SSL_SESSION_free(ctx->sessions); + X509_STORE_free(ctx->cert_store); + ssl_cipher_preference_list_free(ctx->cipher_list); + sk_SSL_CIPHER_free(ctx->cipher_list_by_id); + ssl_cipher_preference_list_free(ctx->cipher_list_tls11); + ssl_cert_free(ctx->cert); + sk_X509_NAME_pop_free(ctx->client_CA, X509_NAME_free); + sk_X509_pop_free(ctx->extra_certs, X509_free); + sk_SRTP_PROTECTION_PROFILE_free(ctx->srtp_profiles); + OPENSSL_free(ctx->psk_identity_hint); + OPENSSL_free(ctx->tlsext_ecpointformatlist); + OPENSSL_free(ctx->tlsext_ellipticcurvelist); + OPENSSL_free(ctx->alpn_client_proto_list); + EVP_PKEY_free(ctx->tlsext_channel_id_private); + BIO_free(ctx->keylog_bio); - OPENSSL_free(a); + OPENSSL_free(ctx); } void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb) { @@ -2051,13 +1833,12 @@ static int ssl_has_key(SSL *s, size_t idx) { return cpk->x509 && cpk->privatekey; } -void ssl_get_compatible_server_ciphers(SSL *s, unsigned long *out_mask_k, - unsigned long *out_mask_a) { +void ssl_get_compatible_server_ciphers(SSL *s, uint32_t *out_mask_k, + uint32_t *out_mask_a) { CERT *c = s->cert; int rsa_enc, rsa_sign, dh_tmp; - unsigned long mask_k, mask_a; + uint32_t mask_k, mask_a; int have_ecc_cert, ecdsa_ok; - int have_ecdh_tmp; X509 *x; if (c == NULL) { @@ -2069,7 +1850,6 @@ void ssl_get_compatible_server_ciphers(SSL *s, unsigned long *out_mask_k, dh_tmp = (c->dh_tmp != NULL || c->dh_tmp_cb != NULL); - have_ecdh_tmp = (c->ecdh_tmp || c->ecdh_tmp_cb || c->ecdh_tmp_auto); rsa_enc = ssl_has_key(s, SSL_PKEY_RSA_ENC); rsa_sign = ssl_has_key(s, SSL_PKEY_RSA_SIGN); have_ecc_cert = ssl_has_key(s, SSL_PKEY_ECC); @@ -2080,14 +1860,12 @@ void ssl_get_compatible_server_ciphers(SSL *s, unsigned long *out_mask_k, mask_k |= SSL_kRSA; } if (dh_tmp) { - mask_k |= SSL_kEDH; + mask_k |= SSL_kDHE; } if (rsa_enc || rsa_sign) { mask_a |= SSL_aRSA; } - mask_a |= SSL_aNULL; - /* An ECC certificate may be usable for ECDSA cipher suites depending on the * key usage extension and on the client's curve preferences. */ if (have_ecc_cert) { @@ -2107,8 +1885,8 @@ void ssl_get_compatible_server_ciphers(SSL *s, unsigned long *out_mask_k, /* If we are considering an ECC cipher suite that uses an ephemeral EC * key, check it. */ - if (have_ecdh_tmp && tls1_check_ec_tmp_key(s)) { - mask_k |= SSL_kEECDH; + if (tls1_check_ec_tmp_key(s)) { + mask_k |= SSL_kECDHE; } /* PSK requires a server callback. */ @@ -2126,11 +1904,9 @@ void ssl_get_compatible_server_ciphers(SSL *s, unsigned long *out_mask_k, (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage))) int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s) { - unsigned long alg_a; - int signature_nid = 0, md_nid = 0, pk_nid = 0; const SSL_CIPHER *cs = s->s3->tmp.new_cipher; - - alg_a = cs->algorithm_auth; + uint32_t alg_a = cs->algorithm_auth; + int signature_nid = 0, md_nid = 0, pk_nid = 0; /* This call populates the ex_flags field correctly */ X509_check_purpose(x, -1, 0); @@ -2175,13 +1951,10 @@ CERT_PKEY *ssl_get_server_send_pkey(const SSL *s) { } EVP_PKEY *ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *cipher) { - unsigned long alg_a; - CERT *c; + uint32_t alg_a = cipher->algorithm_auth; + CERT *c = s->cert; int idx = -1; - alg_a = cipher->algorithm_auth; - c = s->cert; - if (alg_a & SSL_aRSA) { if (c->pkeys[SSL_PKEY_RSA_SIGN].privatekey != NULL) { idx = SSL_PKEY_RSA_SIGN; @@ -2202,56 +1975,62 @@ EVP_PKEY *ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *cipher) { } void ssl_update_cache(SSL *s, int mode) { - int i; - - /* If the session_id_length is 0, we are not supposed to cache it, and it - * would be rather hard to do anyway :-) */ + /* Never cache sessions with empty session IDs. */ if (s->session->session_id_length == 0) { return; } - i = s->initial_ctx->session_cache_mode; - if ((i & mode) && !s->hit && - ((i & SSL_SESS_CACHE_NO_INTERNAL_STORE) || - SSL_CTX_add_session(s->initial_ctx, s->session)) && - s->initial_ctx->new_session_cb != NULL) { - CRYPTO_add(&s->session->references, 1, CRYPTO_LOCK_SSL_SESSION); - if (!s->initial_ctx->new_session_cb(s, s->session)) { + SSL_CTX *ctx = s->initial_ctx; + if ((ctx->session_cache_mode & mode) == mode && !s->hit && + ((ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_STORE) || + SSL_CTX_add_session(ctx, s->session)) && + ctx->new_session_cb != NULL) { + /* Note: |new_session_cb| is called whether the internal session cache is + * used or not. */ + if (!ctx->new_session_cb(s, SSL_SESSION_up_ref(s->session))) { SSL_SESSION_free(s->session); } } - /* auto flush every 255 connections */ - if ((!(i & SSL_SESS_CACHE_NO_AUTO_CLEAR)) && ((i & mode) == mode)) { - if ((((mode & SSL_SESS_CACHE_CLIENT) - ? s->initial_ctx->stats.sess_connect_good - : s->initial_ctx->stats.sess_accept_good) & - 0xff) == 0xff) { - SSL_CTX_flush_sessions(s->initial_ctx, (unsigned long)time(NULL)); + if (!(ctx->session_cache_mode & SSL_SESS_CACHE_NO_AUTO_CLEAR) && + !(ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_STORE) && + (ctx->session_cache_mode & mode) == mode) { + /* Automatically flush the internal session cache every 255 connections. */ + int flush_cache = 0; + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + ctx->handshakes_since_cache_flush++; + if (ctx->handshakes_since_cache_flush >= 255) { + flush_cache = 1; + ctx->handshakes_since_cache_flush = 0; + } + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + + if (flush_cache) { + SSL_CTX_flush_sessions(ctx, (unsigned long)time(NULL)); } } } -int SSL_get_error(const SSL *s, int i) { +int SSL_get_error(const SSL *s, int ret_code) { int reason; - unsigned long l; + uint32_t err; BIO *bio; - if (i > 0) { + if (ret_code > 0) { return SSL_ERROR_NONE; } /* Make things return SSL_ERROR_SYSCALL when doing SSL_do_handshake etc, * where we do encode the error */ - l = ERR_peek_error(); - if (l != 0) { - if (ERR_GET_LIB(l) == ERR_LIB_SYS) { + err = ERR_peek_error(); + if (err != 0) { + if (ERR_GET_LIB(err) == ERR_LIB_SYS) { return SSL_ERROR_SYSCALL; } return SSL_ERROR_SSL; } - if (i == 0) { + if (ret_code == 0) { if ((s->shutdown & SSL_RECEIVED_SHUTDOWN) && (s->s3->warn_alert == SSL_AD_CLOSE_NOTIFY)) { /* The socket was cleanly shut down with a close_notify. */ @@ -2371,24 +2150,6 @@ void SSL_set_connect_state(SSL *s) { ssl_clear_cipher_ctx(s); } -int ssl_undefined_function(SSL *s) { - OPENSSL_PUT_ERROR(SSL, ssl_undefined_function, - ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; -} - -int ssl_undefined_void_function(void) { - OPENSSL_PUT_ERROR(SSL, ssl_undefined_void_function, - ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; -} - -int ssl_undefined_const_function(const SSL *s) { - OPENSSL_PUT_ERROR(SSL, ssl_undefined_const_function, - ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; -} - static const char *ssl_get_version(int version) { switch (version) { case TLS1_2_VERSION: @@ -2403,6 +2164,12 @@ static const char *ssl_get_version(int version) { case SSL3_VERSION: return "SSLv3"; + case DTLS1_VERSION: + return "DTLSv1"; + + case DTLS1_2_VERSION: + return "DTLSv1.2"; + default: return "unknown"; } @@ -2552,15 +2319,11 @@ SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx) { ctx = ssl->initial_ctx; } - if (ssl->cert != NULL) { - ssl_cert_free(ssl->cert); - } - + ssl_cert_free(ssl->cert); ssl->cert = ssl_cert_dup(ctx->cert); + CRYPTO_add(&ctx->references, 1, CRYPTO_LOCK_SSL_CTX); - if (ssl->ctx != NULL) { - SSL_CTX_free(ssl->ctx); /* decrement reference count */ - } + SSL_CTX_free(ssl->ctx); /* decrement reference count */ ssl->ctx = ctx; ssl->sid_ctx_length = ctx->sid_ctx_length; @@ -2599,8 +2362,12 @@ long SSL_get_verify_result(const SSL *ssl) { return ssl->verify_result; } int SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) { - return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, argl, argp, new_func, - dup_func, free_func); + int index; + if (!CRYPTO_get_ex_new_index(&g_ex_data_class_ssl, &index, argl, argp, + new_func, dup_func, free_func)) { + return -1; + } + return index; } int SSL_set_ex_data(SSL *s, int idx, void *arg) { @@ -2614,8 +2381,12 @@ void *SSL_get_ex_data(const SSL *s, int idx) { int SSL_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) { - return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_CTX, argl, argp, new_func, - dup_func, free_func); + int index; + if (!CRYPTO_get_ex_new_index(&g_ex_data_class_ssl_ctx, &index, argl, argp, + new_func, dup_func, free_func)) { + return -1; + } + return index; } int SSL_CTX_set_ex_data(SSL_CTX *s, int idx, void *arg) { @@ -2633,9 +2404,7 @@ X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *ctx) { } void SSL_CTX_set_cert_store(SSL_CTX *ctx, X509_STORE *store) { - if (ctx->cert_store != NULL) { - X509_STORE_free(ctx->cert_store); - } + X509_STORE_free(ctx->cert_store); ctx->cert_store = store; } @@ -2644,35 +2413,33 @@ int SSL_want(const SSL *s) { return s->rwstate; } void SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx, RSA *(*cb)(SSL *ssl, int is_export, int keylength)) { - SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_TMP_RSA_CB, (void (*)(void))cb); } void SSL_set_tmp_rsa_callback(SSL *ssl, RSA *(*cb)(SSL *ssl, int is_export, int keylength)) { - SSL_callback_ctrl(ssl, SSL_CTRL_SET_TMP_RSA_CB, (void (*)(void))cb); } void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx, - DH *(*dh)(SSL *ssl, int is_export, - int keylength)) { - SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_TMP_DH_CB, (void (*)(void))dh); + DH *(*callback)(SSL *ssl, int is_export, + int keylength)) { + ctx->cert->dh_tmp_cb = callback; } -void SSL_set_tmp_dh_callback(SSL *ssl, DH *(*dh)(SSL *ssl, int is_export, - int keylength)) { - SSL_callback_ctrl(ssl, SSL_CTRL_SET_TMP_DH_CB, (void (*)(void))dh); +void SSL_set_tmp_dh_callback(SSL *ssl, DH *(*callback)(SSL *ssl, int is_export, + int keylength)) { + ssl->cert->dh_tmp_cb = callback; } void SSL_CTX_set_tmp_ecdh_callback(SSL_CTX *ctx, - EC_KEY *(*ecdh)(SSL *ssl, int is_export, - int keylength)) { - SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_TMP_ECDH_CB, (void (*)(void))ecdh); + EC_KEY *(*callback)(SSL *ssl, int is_export, + int keylength)) { + ctx->cert->ecdh_tmp_cb = callback; } void SSL_set_tmp_ecdh_callback(SSL *ssl, - EC_KEY *(*ecdh)(SSL *ssl, int is_export, - int keylength)) { - SSL_callback_ctrl(ssl, SSL_CTRL_SET_TMP_ECDH_CB, (void (*)(void))ecdh); + EC_KEY *(*callback)(SSL *ssl, int is_export, + int keylength)) { + ssl->cert->ecdh_tmp_cb = callback; } int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint) { @@ -2682,9 +2449,7 @@ int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint) { return 0; } - if (ctx->psk_identity_hint != NULL) { - OPENSSL_free(ctx->psk_identity_hint); - } + OPENSSL_free(ctx->psk_identity_hint); if (identity_hint != NULL) { ctx->psk_identity_hint = BUF_strdup(identity_hint); @@ -2710,10 +2475,8 @@ int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint) { } /* Clear currently configured hint, if any. */ - if (s->psk_identity_hint != NULL) { - OPENSSL_free(s->psk_identity_hint); - s->psk_identity_hint = NULL; - } + OPENSSL_free(s->psk_identity_hint); + s->psk_identity_hint = NULL; if (identity_hint != NULL) { s->psk_identity_hint = BUF_strdup(identity_hint); @@ -2786,19 +2549,26 @@ void SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)) { - SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb); + ctx->msg_callback = cb; +} + +void SSL_CTX_set_msg_callback_arg(SSL_CTX *ctx, void *arg) { + ctx->msg_callback_arg = arg; } + void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)) { - SSL_callback_ctrl(ssl, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb); + ssl->msg_callback = cb; +} + +void SSL_set_msg_callback_arg(SSL *ssl, void *arg) { + ssl->msg_callback_arg = arg; } void SSL_CTX_set_keylog_bio(SSL_CTX *ctx, BIO *keylog_bio) { - if (ctx->keylog_bio != NULL) { - BIO_free(ctx->keylog_bio); - } + BIO_free(ctx->keylog_bio); ctx->keylog_bio = keylog_bio; } @@ -2904,19 +2674,12 @@ int ssl_ctx_log_master_secret(SSL_CTX *ctx, const uint8_t *client_random, return ret; } +int SSL_in_false_start(const SSL *s) { + return s->s3->tmp.in_false_start; +} + int SSL_cutthrough_complete(const SSL *s) { - return ( - !s->server && /* cutthrough only applies to clients */ - !s->hit && /* full-handshake */ - s->version >= SSL3_VERSION && - s->s3->in_read_app_data == 0 && /* cutthrough only applies to write() */ - (SSL_get_mode((SSL *)s) & - SSL_MODE_HANDSHAKE_CUTTHROUGH) && /* cutthrough enabled */ - ssl3_can_cutthrough(s) && /* cutthrough allowed */ - s->s3->previous_server_finished_len == - 0 && /* not a renegotiation handshake */ - (s->state == SSL3_ST_CR_SESSION_TICKET_A || /* ready to write app-data*/ - s->state == SSL3_ST_CR_CHANGE || s->state == SSL3_ST_CR_FINISHED_A)); + return SSL_in_false_start(s); } void SSL_get_structure_sizes(size_t *ssl_size, size_t *ssl_ctx_size, @@ -2926,27 +2689,18 @@ void SSL_get_structure_sizes(size_t *ssl_size, size_t *ssl_ctx_size, *ssl_session_size = sizeof(SSL_SESSION); } -int ssl3_can_cutthrough(const SSL *s) { - const SSL_CIPHER *c; - - /* require a strong enough cipher */ - if (SSL_get_cipher_bits(s, NULL) < 128) { - return 0; - } - - /* require ALPN or NPN extension */ - if (!s->s3->alpn_selected && !s->s3->next_proto_neg_seen) { - return 0; - } - - /* require a forward-secret cipher */ - c = SSL_get_current_cipher(s); - if (!c || - (c->algorithm_mkey != SSL_kEDH && c->algorithm_mkey != SSL_kEECDH)) { - return 0; - } +int ssl3_can_false_start(const SSL *s) { + const SSL_CIPHER *const cipher = SSL_get_current_cipher(s); - return 1; + /* False Start only for TLS 1.2 with an ECDHE+AEAD cipher and ALPN or NPN. */ + return !SSL_IS_DTLS(s) && + SSL_version(s) >= TLS1_2_VERSION && + (s->s3->alpn_selected || s->s3->next_proto_neg_seen) && + cipher != NULL && + cipher->algorithm_mkey == SSL_kECDHE && + (cipher->algorithm_enc == SSL_AES128GCM || + cipher->algorithm_enc == SSL_AES256GCM || + cipher->algorithm_enc == SSL_CHACHA20POLY1305); } const SSL3_ENC_METHOD *ssl3_get_enc_method(uint16_t version) { @@ -2957,18 +2711,14 @@ const SSL3_ENC_METHOD *ssl3_get_enc_method(uint16_t version) { case TLS1_VERSION: return &TLSv1_enc_data; + case DTLS1_VERSION: case TLS1_1_VERSION: return &TLSv1_1_enc_data; + case DTLS1_2_VERSION: case TLS1_2_VERSION: return &TLSv1_2_enc_data; - case DTLS1_VERSION: - return &DTLSv1_enc_data; - - case DTLS1_2_VERSION: - return &DTLSv1_2_enc_data; - default: return NULL; } @@ -3016,7 +2766,7 @@ uint16_t ssl3_get_mutual_version(SSL *s, uint16_t client_version) { if (client_version <= DTLS1_2_VERSION && !(s->options & SSL_OP_NO_DTLSv1_2)) { version = DTLS1_2_VERSION; } else if (client_version <= DTLS1_VERSION && - !(s->options & SSL_OP_NO_DTLSv1)) { + !(s->options & SSL_OP_NO_DTLSv1)) { version = DTLS1_VERSION; } @@ -3051,7 +2801,7 @@ uint16_t ssl3_get_mutual_version(SSL *s, uint16_t client_version) { } uint16_t ssl3_get_max_client_version(SSL *s) { - unsigned long options = s->options; + uint32_t options = s->options; uint16_t version = 0; /* OpenSSL's API for controlling versions entails blacklisting individual @@ -3169,6 +2919,41 @@ int SSL_cache_hit(SSL *s) { return s->hit; } int SSL_is_server(SSL *s) { return s->server; } +void SSL_CTX_set_dos_protection_cb( + SSL_CTX *ctx, int (*cb)(const struct ssl_early_callback_ctx *)) { + ctx->dos_protection_cb = cb; +} + void SSL_enable_fastradio_padding(SSL *s, char on_off) { s->fastradio_padding = on_off; } + +void SSL_set_reject_peer_renegotiations(SSL *s, int reject) { + s->reject_peer_renegotiations = !!reject; +} + +const SSL_CIPHER *SSL_get_cipher_by_value(uint16_t value) { + return ssl3_get_cipher_by_value(value); +} + +int SSL_get_rc4_state(const SSL *ssl, const RC4_KEY **read_key, + const RC4_KEY **write_key) { + if (ssl->aead_read_ctx == NULL || ssl->aead_write_ctx == NULL) { + return 0; + } + + return EVP_AEAD_CTX_get_rc4_state(&ssl->aead_read_ctx->ctx, read_key) && + EVP_AEAD_CTX_get_rc4_state(&ssl->aead_write_ctx->ctx, write_key); +} + +int SSL_CTX_sess_connect(const SSL_CTX *ctx) { return 0; } +int SSL_CTX_sess_connect_good(const SSL_CTX *ctx) { return 0; } +int SSL_CTX_sess_connect_renegotiate(const SSL_CTX *ctx) { return 0; } +int SSL_CTX_sess_accept(const SSL_CTX *ctx) { return 0; } +int SSL_CTX_sess_accept_renegotiate(const SSL_CTX *ctx) { return 0; } +int SSL_CTX_sess_accept_good(const SSL_CTX *ctx) { return 0; } +int SSL_CTX_sess_hits(const SSL_CTX *ctx) { return 0; } +int SSL_CTX_sess_cb_hits(const SSL_CTX *ctx) { return 0; } +int SSL_CTX_sess_misses(const SSL_CTX *ctx) { return 0; } +int SSL_CTX_sess_timeouts(const SSL_CTX *ctx) { return 0; } +int SSL_CTX_sess_cache_full(const SSL_CTX *ctx) { return 0; } |