X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fssl_lib.c;h=846b856af497c58d295a9b817684e1422d18f101;hp=41574c4bf24c2fe9f2963cd47f7224d989edc3a5;hb=18958cefd82449daf3c589b74a074f0c88159d47;hpb=5fe371570770e46f2d9e19e8b81c8bc0d47ec0d6 diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 41574c4bf2..846b856af4 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -23,8 +23,6 @@ #include "internal/cryptlib.h" #include "internal/refcount.h" -const char SSL_version_str[] = OPENSSL_VERSION_TEXT; - static int ssl_undefined_function_1(SSL *ssl, SSL3_RECORD *r, size_t s, int t) { (void)r; @@ -591,6 +589,7 @@ int SSL_clear(SSL *s) s->psksession_id = NULL; s->psksession_id_len = 0; s->hello_retry_request = 0; + s->sent_tickets = 0; s->error = 0; s->hit = 0; @@ -653,6 +652,10 @@ int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth) ctx->method = meth; + if (!SSL_CTX_set_ciphersuites(ctx, TLS_DEFAULT_CIPHERSUITES)) { + SSLerr(SSL_F_SSL_CTX_SET_SSL_VERSION, SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS); + return 0; + } sk = ssl_create_cipher_list(ctx->method, ctx->tls13_ciphersuites, &(ctx->cipher_list), @@ -699,6 +702,9 @@ SSL *SSL_new(SSL_CTX *ctx) 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); @@ -803,6 +809,9 @@ SSL *SSL_new(SSL_CTX *ctx) s->key_update = SSL_KEY_UPDATE_NONE; + s->allow_early_data_cb = ctx->allow_early_data_cb; + s->allow_early_data_cb_data = ctx->allow_early_data_cb_data; + if (!s->method->ssl_new(s)) goto err; @@ -2258,7 +2267,6 @@ LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx) long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) { long l; - int i; /* For some cases with ctx == NULL perform syntax checks */ if (ctx == NULL) { switch (cmd) { @@ -2313,40 +2321,27 @@ long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) case SSL_CTRL_SESS_NUMBER: return lh_SSL_SESSION_num_items(ctx->sessions); case SSL_CTRL_SESS_CONNECT: - return CRYPTO_atomic_read(&ctx->stats.sess_connect, &i, ctx->lock) - ? i : 0; + return tsan_load(&ctx->stats.sess_connect); case SSL_CTRL_SESS_CONNECT_GOOD: - return CRYPTO_atomic_read(&ctx->stats.sess_connect_good, &i, ctx->lock) - ? i : 0; + return tsan_load(&ctx->stats.sess_connect_good); case SSL_CTRL_SESS_CONNECT_RENEGOTIATE: - return CRYPTO_atomic_read(&ctx->stats.sess_connect_renegotiate, &i, - ctx->lock) - ? i : 0; + return tsan_load(&ctx->stats.sess_connect_renegotiate); case SSL_CTRL_SESS_ACCEPT: - return CRYPTO_atomic_read(&ctx->stats.sess_accept, &i, ctx->lock) - ? i : 0; + return tsan_load(&ctx->stats.sess_accept); case SSL_CTRL_SESS_ACCEPT_GOOD: - return CRYPTO_atomic_read(&ctx->stats.sess_accept_good, &i, ctx->lock) - ? i : 0; + return tsan_load(&ctx->stats.sess_accept_good); case SSL_CTRL_SESS_ACCEPT_RENEGOTIATE: - return CRYPTO_atomic_read(&ctx->stats.sess_accept_renegotiate, &i, - ctx->lock) - ? i : 0; + return tsan_load(&ctx->stats.sess_accept_renegotiate); case SSL_CTRL_SESS_HIT: - return CRYPTO_atomic_read(&ctx->stats.sess_hit, &i, ctx->lock) - ? i : 0; + return tsan_load(&ctx->stats.sess_hit); case SSL_CTRL_SESS_CB_HIT: - return CRYPTO_atomic_read(&ctx->stats.sess_cb_hit, &i, ctx->lock) - ? i : 0; + return tsan_load(&ctx->stats.sess_cb_hit); case SSL_CTRL_SESS_MISSES: - return CRYPTO_atomic_read(&ctx->stats.sess_miss, &i, ctx->lock) - ? i : 0; + return tsan_load(&ctx->stats.sess_miss); case SSL_CTRL_SESS_TIMEOUTS: - return CRYPTO_atomic_read(&ctx->stats.sess_timeout, &i, ctx->lock) - ? i : 0; + return tsan_load(&ctx->stats.sess_timeout); case SSL_CTRL_SESS_CACHE_FULL: - return CRYPTO_atomic_read(&ctx->stats.sess_cache_full, &i, ctx->lock) - ? i : 0; + return tsan_load(&ctx->stats.sess_cache_full); case SSL_CTRL_MODE: return (ctx->mode |= larg); case SSL_CTRL_CLEAR_MODE: @@ -2606,8 +2601,15 @@ const char *SSL_get_servername(const SSL *s, const int type) if (type != TLSEXT_NAMETYPE_host_name) return NULL; - return s->session && !s->ext.hostname ? - s->session->ext.hostname : s->ext.hostname; + /* + * SNI is not negotiated in pre-TLS-1.3 resumption flows, so fake up an + * SNI value to return if we are resuming/resumed. N.B. that we still + * call the relevant callbacks for such resumption flows, and callbacks + * might error out if there is not a SNI value available. + */ + if (s->hit) + return s->session->ext.hostname; + return s->ext.hostname; } int SSL_get_servername_type(const SSL *s) @@ -2894,6 +2896,7 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) 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; /* We take the system default. */ @@ -3033,6 +3036,19 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) */ ret->max_early_data = 0; + /* + * Default recv_max_early_data is a fully loaded single record. Could be + * split across multiple records in practice. We set this differently to + * max_early_data so that, in the default case, we do not advertise any + * support for early_data, but if a client were to send us some (e.g. + * 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; + + /* By default we send two session tickets automatically in TLSv1.3 */ + ret->num_tickets = 2; + ssl_ctx_system_config(ret); return ret; @@ -3360,24 +3376,47 @@ void ssl_update_cache(SSL *s, int mode) i = s->session_ctx->session_cache_mode; if ((i & mode) != 0 - && (!s->hit || SSL_IS_TLS13(s)) - && ((i & SSL_SESS_CACHE_NO_INTERNAL_STORE) != 0 - || SSL_CTX_add_session(s->session_ctx, s->session)) - && s->session_ctx->new_session_cb != NULL) { - SSL_SESSION_up_ref(s->session); - if (!s->session_ctx->new_session_cb(s, s->session)) - SSL_SESSION_free(s->session); + && (!s->hit || SSL_IS_TLS13(s))) { + /* + * Add the session to the internal cache. In server side TLSv1.3 we + * normally don't do this because by default it's a full stateless ticket + * with only a dummy session id so there is no reason to cache it, + * unless: + * - we are doing early_data, in which case we cache so that we can + * detect replays + * - the application has set a remove_session_cb so needs to know about + * 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_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); + + /* + * 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(s, s->session)) + SSL_SESSION_free(s->session); + } } /* auto flush every 255 connections */ if ((!(i & SSL_SESS_CACHE_NO_AUTO_CLEAR)) && ((i & mode) == mode)) { - int *stat, val; + TSAN_QUALIFIER int *stat; if (mode & SSL_SESS_CACHE_CLIENT) stat = &s->session_ctx->stats.sess_connect_good; else stat = &s->session_ctx->stats.sess_accept_good; - if (CRYPTO_atomic_read(stat, &val, s->session_ctx->lock) - && (val & 0xff) == 0xff) + if ((tsan_load(stat) & 0xff) == 0xff) SSL_CTX_flush_sessions(s->session_ctx, (unsigned long)time(NULL)); } } @@ -3522,12 +3561,6 @@ int SSL_do_handshake(SSL *s) s->method->ssl_renegotiate_check(s, 0); - if (SSL_is_server(s)) { - /* clear SNI settings at server-side */ - OPENSSL_free(s->ext.hostname); - s->ext.hostname = NULL; - } - if (SSL_in_init(s) || SSL_in_before(s)) { if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) { struct ssl_async_args args; @@ -4314,6 +4347,30 @@ int SSL_set_block_padding(SSL *ssl, size_t block_size) return 1; } +int SSL_set_num_tickets(SSL *s, size_t num_tickets) +{ + s->num_tickets = num_tickets; + + return 1; +} + +size_t SSL_get_num_tickets(SSL *s) +{ + return s->num_tickets; +} + +int SSL_CTX_set_num_tickets(SSL_CTX *ctx, size_t num_tickets) +{ + ctx->num_tickets = num_tickets; + + return 1; +} + +size_t SSL_CTX_get_num_tickets(SSL_CTX *ctx) +{ + return ctx->num_tickets; +} + /* * Allocates new EVP_MD_CTX and sets pointer to it into given pointer * variable, freeing EVP_MD_CTX previously stored in that variable, if any. @@ -5319,6 +5376,30 @@ uint32_t SSL_get_max_early_data(const SSL *s) return s->max_early_data; } +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; + + return 1; +} + +uint32_t SSL_CTX_get_recv_max_early_data(const SSL_CTX *ctx) +{ + return ctx->recv_max_early_data; +} + +int SSL_set_recv_max_early_data(SSL *s, uint32_t recv_max_early_data) +{ + s->recv_max_early_data = recv_max_early_data; + + return 1; +} + +uint32_t SSL_get_recv_max_early_data(const SSL *s) +{ + return s->recv_max_early_data; +} + __owur unsigned int ssl_get_max_send_fragment(const SSL *ssl) { /* Return any active Max Fragment Len extension */ @@ -5367,9 +5448,14 @@ int SSL_stateless(SSL *s) return -1; } -void SSL_force_post_handshake_auth(SSL *ssl) +void SSL_CTX_set_post_handshake_auth(SSL_CTX *ctx, int val) +{ + ctx->pha_enabled = val; +} + +void SSL_set_post_handshake_auth(SSL *ssl, int val) { - ssl->pha_forced = 1; + ssl->pha_enabled = val; } int SSL_verify_client_post_handshake(SSL *ssl) @@ -5429,3 +5515,19 @@ int SSL_CTX_set_session_ticket_cb(SSL_CTX *ctx, ctx->ticket_cb_data = arg; return 1; } + +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; +} + +void SSL_set_allow_early_data_cb(SSL *s, + SSL_allow_early_data_cb_fn cb, + void *arg) +{ + s->allow_early_data_cb = cb; + s->allow_early_data_cb_data = arg; +}