X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fssl_lib.c;h=1dd355d0dadd4357480b490deb2b38496c5c0fb3;hp=b66cd71d900f939e0d3a82ef8291abcc6e2ff46e;hb=ee94ec2ef88e0ec25dedf2829d8e48dff0aa1c50;hpb=d316cdcf6d8d6934663278145fe0a8191e14a8c5 diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index b66cd71d90..1dd355d0da 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -591,6 +591,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; @@ -699,6 +700,7 @@ 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->num_tickets = ctx->num_tickets; /* Shallow copy of the ciphersuites stack */ s->tls13_ciphersuites = sk_SSL_CIPHER_dup(ctx->tls13_ciphersuites); @@ -1127,7 +1129,6 @@ void SSL_free(SSL *s) if (s == NULL) return; - CRYPTO_DOWN_REF(&s->references, &i, s->lock); REF_PRINT_COUNT("SSL", s); if (i > 0) @@ -2024,6 +2025,9 @@ int SSL_write_early_data(SSL *s, const void *buf, size_t num, size_t *written) /* We are a server writing to an unauthenticated client */ s->early_data_state = SSL_EARLY_DATA_UNAUTH_WRITING; ret = SSL_write_ex(s, buf, num, written); + /* The buffering BIO is still in place */ + if (ret) + (void)BIO_flush(s->wbio); s->early_data_state = early_data_state; return ret; @@ -2550,121 +2554,37 @@ int SSL_set_cipher_list(SSL *s, const char *str) return 1; } -static int ciphersuite_cb(const char *elem, int len, void *arg) -{ - STACK_OF(SSL_CIPHER) *ciphersuites = (STACK_OF(SSL_CIPHER) *)arg; - const SSL_CIPHER *cipher; - /* Arbitrary sized temp buffer for the cipher name. Should be big enough */ - char name[80]; - - if (len > (int)(sizeof(name) - 1)) { - SSLerr(SSL_F_CIPHERSUITE_CB, SSL_R_NO_CIPHER_MATCH); - return 0; - } - - memcpy(name, elem, len); - name[len] = '\0'; - - cipher = ssl3_get_cipher_by_std_name(name); - if (cipher == NULL) { - SSLerr(SSL_F_CIPHERSUITE_CB, SSL_R_NO_CIPHER_MATCH); - return 0; - } - - if (!sk_SSL_CIPHER_push(ciphersuites, cipher)) { - SSLerr(SSL_F_CIPHERSUITE_CB, ERR_R_INTERNAL_ERROR); - return 0; - } - - return 1; -} - -static int set_ciphersuites(STACK_OF(SSL_CIPHER) **currciphers, const char *str) -{ - STACK_OF(SSL_CIPHER) *newciphers = sk_SSL_CIPHER_new_null(); - - if (newciphers == NULL) - return 0; - - /* Parse the list. We explicitly allow an empty list */ - if (*str != '\0' - && !CONF_parse_list(str, ':', 1, ciphersuite_cb, newciphers)) { - sk_SSL_CIPHER_free(newciphers); - return 0; - } - sk_SSL_CIPHER_free(*currciphers); - *currciphers = newciphers; - - return 1; -} - -static int update_cipher_list(STACK_OF(SSL_CIPHER) *cipher_list, - STACK_OF(SSL_CIPHER) *tls13_ciphersuites) -{ - int i; - - /* - * Delete any existing TLSv1.3 ciphersuites. These are always first in the - * list. - */ - while (sk_SSL_CIPHER_num(cipher_list) > 0 - && sk_SSL_CIPHER_value(cipher_list, 0)->min_tls == TLS1_3_VERSION) - sk_SSL_CIPHER_delete(cipher_list, 0); - - /* Insert the new TLSv1.3 ciphersuites */ - for (i = 0; i < sk_SSL_CIPHER_num(tls13_ciphersuites); i++) - sk_SSL_CIPHER_insert(cipher_list, - sk_SSL_CIPHER_value(tls13_ciphersuites, i), i); - - return 1; -} - -int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str) -{ - int ret = set_ciphersuites(&(ctx->tls13_ciphersuites), str); - - if (ret && ctx->cipher_list != NULL) { - /* We already have a cipher_list, so we need to update it */ - return update_cipher_list(ctx->cipher_list, ctx->tls13_ciphersuites); - } - - return ret; -} - -int SSL_set_ciphersuites(SSL *s, const char *str) -{ - int ret = set_ciphersuites(&(s->tls13_ciphersuites), str); - - if (ret && s->cipher_list != NULL) { - /* We already have a cipher_list, so we need to update it */ - return update_cipher_list(s->cipher_list, s->tls13_ciphersuites); - } - - return ret; -} - -char *SSL_get_shared_ciphers(const SSL *s, char *buf, int len) +char *SSL_get_shared_ciphers(const SSL *s, char *buf, int size) { char *p; - STACK_OF(SSL_CIPHER) *sk; + STACK_OF(SSL_CIPHER) *clntsk, *srvrsk; const SSL_CIPHER *c; int i; - if ((s->session == NULL) || (s->session->ciphers == NULL) || (len < 2)) + if (!s->server + || s->session == NULL + || s->session->ciphers == NULL + || size < 2) return NULL; p = buf; - sk = s->session->ciphers; + clntsk = s->session->ciphers; + srvrsk = SSL_get_ciphers(s); + if (clntsk == NULL || srvrsk == NULL) + return NULL; - if (sk_SSL_CIPHER_num(sk) == 0) + if (sk_SSL_CIPHER_num(clntsk) == 0 || sk_SSL_CIPHER_num(srvrsk) == 0) return NULL; - for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) { + for (i = 0; i < sk_SSL_CIPHER_num(clntsk); i++) { int n; - c = sk_SSL_CIPHER_value(sk, i); + c = sk_SSL_CIPHER_value(clntsk, i); + if (sk_SSL_CIPHER_find(srvrsk, c) < 0) + continue; + n = strlen(c->name); - if (n + 1 > len) { + if (n + 1 > size) { if (p != buf) --p; *p = '\0'; @@ -2673,7 +2593,7 @@ char *SSL_get_shared_ciphers(const SSL *s, char *buf, int len) strcpy(p, c->name); p += n; *(p++) = ':'; - len -= n + 1; + size -= n + 1; } p[-1] = '\0'; return buf; @@ -3048,13 +2968,13 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) /* Setup RFC5077 ticket keys */ if ((RAND_bytes(ret->ext.tick_key_name, sizeof(ret->ext.tick_key_name)) <= 0) - || (RAND_bytes(ret->ext.secure->tick_hmac_key, + || (RAND_priv_bytes(ret->ext.secure->tick_hmac_key, sizeof(ret->ext.secure->tick_hmac_key)) <= 0) - || (RAND_bytes(ret->ext.secure->tick_aes_key, + || (RAND_priv_bytes(ret->ext.secure->tick_aes_key, sizeof(ret->ext.secure->tick_aes_key)) <= 0)) ret->options |= SSL_OP_NO_TICKET; - if (RAND_bytes(ret->ext.cookie_hmac_key, + if (RAND_priv_bytes(ret->ext.cookie_hmac_key, sizeof(ret->ext.cookie_hmac_key)) <= 0) goto err; @@ -3115,6 +3035,9 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) */ ret->max_early_data = 0; + /* By default we send two session tickets automatically in TLSv1.3 */ + ret->num_tickets = 2; + ssl_ctx_system_config(ret); return ret; @@ -3430,24 +3353,45 @@ void ssl_update_cache(SSL *s, int mode) /* * If sid_ctx_length is 0 there is no specific application context * associated with this session, so when we try to resume it and - * SSL_VERIFY_PEER is requested, we have no indication that this is - * actually a session for the proper application context, and the - * *handshake* will fail, not just the resumption attempt. - * Do not cache these sessions that are not resumable. + * SSL_VERIFY_PEER is requested to verify the client identity, we have no + * indication that this is actually a session for the proper application + * context, and the *handshake* will fail, not just the resumption attempt. + * Do not cache (on the server) these sessions that are not resumable + * (clients can set SSL_VERIFY_PEER without needing a sid_ctx set). */ - if (s->session->sid_ctx_length == 0 + if (s->server && s->session->sid_ctx_length == 0 && (s->verify_mode & SSL_VERIFY_PEER) != 0) return; 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 its 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 + */ + if ((i & SSL_SESS_CACHE_NO_INTERNAL_STORE) == 0 + && (!SSL_IS_TLS13(s) + || !s->server + || s->max_early_data > 0 + || s->session_ctx->remove_session_cb != NULL)) + 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 */ @@ -3938,8 +3882,6 @@ int ssl_free_wbio_buffer(SSL *s) return 1; s->wbio = BIO_pop(s->wbio); - if (!ossl_assert(s->wbio != NULL)) - return 0; BIO_free(s->bbio); s->bbio = NULL; @@ -4397,6 +4339,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. @@ -5049,9 +5015,11 @@ int SSL_client_hello_get1_extensions_present(SSL *s, int **out, size_t *outlen) if (ext->present) num++; } - present = OPENSSL_malloc(sizeof(*present) * num); - if (present == NULL) + if ((present = OPENSSL_malloc(sizeof(*present) * num)) == NULL) { + SSLerr(SSL_F_SSL_CLIENT_HELLO_GET1_EXTENSIONS_PRESENT, + ERR_R_MALLOC_FAILURE); return 0; + } for (i = 0; i < s->clienthello->pre_proc_exts_len; i++) { ext = s->clienthello->pre_proc_exts + i; if (ext->present) {