diff options
-rw-r--r-- | apps/apps.h | 6 | ||||
-rw-r--r-- | apps/ciphers.c | 14 | ||||
-rw-r--r-- | crypto/err/openssl.txt | 1 | ||||
-rw-r--r-- | include/openssl/ssl.h | 2 | ||||
-rw-r--r-- | include/openssl/sslerr.h | 1 | ||||
-rw-r--r-- | include/openssl/tls1.h | 12 | ||||
-rw-r--r-- | ssl/s3_lib.c | 192 | ||||
-rw-r--r-- | ssl/ssl_ciph.c | 21 | ||||
-rw-r--r-- | ssl/ssl_conf.c | 13 | ||||
-rw-r--r-- | ssl/ssl_err.c | 1 | ||||
-rw-r--r-- | ssl/ssl_lib.c | 122 | ||||
-rw-r--r-- | ssl/ssl_locl.h | 12 | ||||
-rw-r--r-- | test/cipherlist_test.c | 14 | ||||
-rw-r--r-- | test/clienthellotest.c | 3 | ||||
-rw-r--r-- | test/fatalerrtest.c | 4 | ||||
-rw-r--r-- | test/recipes/70-test_sslsigalgs.t | 18 | ||||
-rw-r--r-- | test/recipes/70-test_tls13hrr.t | 5 | ||||
-rw-r--r-- | test/recipes/70-test_tls13psk.t | 6 | ||||
-rw-r--r-- | test/recipes/80-test_ssl_old.t | 21 | ||||
-rw-r--r-- | test/ssl-tests/02-protocol-version.conf | 2 | ||||
-rw-r--r-- | test/ssl-tests/protocol_version.pm | 2 | ||||
-rw-r--r-- | test/sslapitest.c | 22 | ||||
-rw-r--r-- | test/sslcorrupttest.c | 12 | ||||
-rw-r--r-- | test/ssltest_old.c | 17 | ||||
-rw-r--r-- | util/libssl.num | 2 | ||||
-rw-r--r-- | util/perl/TLSProxy/Proxy.pm | 30 |
26 files changed, 383 insertions, 172 deletions
diff --git a/apps/apps.h b/apps/apps.h index aa63527675..8f2590e5c8 100644 --- a/apps/apps.h +++ b/apps/apps.h @@ -229,7 +229,7 @@ int set_cert_times(X509 *x, const char *startdate, const char *enddate, OPT_S_ONRESUMP, OPT_S_NOLEGACYCONN, OPT_S_ALLOW_NO_DHE_KEX, \ OPT_S_PRIORITIZE_CHACHA, \ OPT_S_STRICT, OPT_S_SIGALGS, OPT_S_CLIENTSIGALGS, OPT_S_GROUPS, \ - OPT_S_CURVES, OPT_S_NAMEDCURVE, OPT_S_CIPHER, \ + OPT_S_CURVES, OPT_S_NAMEDCURVE, OPT_S_CIPHER, OPT_S_CIPHERSUITES, \ OPT_S_RECORD_PADDING, OPT_S_DEBUGBROKE, OPT_S_COMP, \ OPT_S_NO_RENEGOTIATION, OPT_S_NO_MIDDLEBOX, OPT_S__LAST @@ -272,7 +272,8 @@ int set_cert_times(X509 *x, const char *startdate, const char *enddate, "Groups to advertise (colon-separated list)" }, \ {"named_curve", OPT_S_NAMEDCURVE, 's', \ "Elliptic curve used for ECDHE (server-side only)" }, \ - {"cipher", OPT_S_CIPHER, 's', "Specify cipher list to be used"}, \ + {"cipher", OPT_S_CIPHER, 's', "Specify TLSv1.2 and below cipher list to be used"}, \ + {"ciphersuites", OPT_S_CIPHERSUITES, 's', "Specify TLSv1.3 ciphersuites to be used"}, \ {"record_padding", OPT_S_RECORD_PADDING, 's', \ "Block size to pad TLS 1.3 records to."}, \ {"debug_broken_protocol", OPT_S_DEBUGBROKE, '-', \ @@ -305,6 +306,7 @@ int set_cert_times(X509 *x, const char *startdate, const char *enddate, case OPT_S_CURVES: \ case OPT_S_NAMEDCURVE: \ case OPT_S_CIPHER: \ + case OPT_S_CIPHERSUITES: \ case OPT_S_RECORD_PADDING: \ case OPT_S_NO_RENEGOTIATION: \ case OPT_S_DEBUGBROKE: \ diff --git a/apps/ciphers.c b/apps/ciphers.c index 4e8ffd13ce..0bb33a4aca 100644 --- a/apps/ciphers.c +++ b/apps/ciphers.c @@ -26,6 +26,7 @@ typedef enum OPTION_choice { OPT_TLS1_3, OPT_PSK, OPT_SRP, + OPT_CIPHERSUITES, OPT_V, OPT_UPPER_V, OPT_S } OPTION_CHOICE; @@ -57,6 +58,8 @@ const OPTIONS ciphers_options[] = { {"srp", OPT_SRP, '-', "include ciphersuites requiring SRP"}, #endif {"convert", OPT_CONVERT, 's', "Convert standard name into OpenSSL name"}, + {"ciphersuites", OPT_CIPHERSUITES, 's', + "Configure the TLSv1.3 ciphersuites to use"}, {NULL} }; @@ -91,7 +94,7 @@ int ciphers_main(int argc, char **argv) int srp = 0; #endif const char *p; - char *ciphers = NULL, *prog, *convert = NULL; + char *ciphers = NULL, *prog, *convert = NULL, *ciphersuites = NULL; char buf[512]; OPTION_CHOICE o; int min_version = 0, max_version = 0; @@ -153,6 +156,9 @@ int ciphers_main(int argc, char **argv) srp = 1; #endif break; + case OPT_CIPHERSUITES: + ciphersuites = opt_arg(); + break; } } argv = opt_rest(); @@ -185,6 +191,12 @@ int ciphers_main(int argc, char **argv) if (srp) SSL_CTX_set_srp_client_pwd_callback(ctx, dummy_srp); #endif + + if (ciphersuites != NULL && !SSL_CTX_set_ciphersuites(ctx, ciphersuites)) { + BIO_printf(bio_err, "Error setting TLSv1.3 ciphersuites\n"); + goto err; + } + if (ciphers != NULL) { if (!SSL_CTX_set_cipher_list(ctx, ciphers)) { BIO_printf(bio_err, "Error in cipher list\n"); diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index d867007b2e..606f2b1552 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -986,6 +986,7 @@ SSL_F_ADD_CLIENT_KEY_SHARE_EXT:438:* SSL_F_ADD_KEY_SHARE:512:add_key_share SSL_F_BYTES_TO_CIPHER_LIST:519:bytes_to_cipher_list SSL_F_CHECK_SUITEB_CIPHER_LIST:331:check_suiteb_cipher_list +SSL_F_CIPHERSUITE_CB:621:ciphersuite_cb SSL_F_CONSTRUCT_CA_NAMES:552:construct_ca_names SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS:553:construct_key_exchange_tbs SSL_F_CREATE_SYNTHETIC_MESSAGE_HASH:539:create_synthetic_message_hash diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index ec29405c50..f2b5f36cdb 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -1500,6 +1500,8 @@ void SSL_set_bio(SSL *s, BIO *rbio, BIO *wbio); __owur BIO *SSL_get_rbio(const SSL *s); __owur BIO *SSL_get_wbio(const SSL *s); __owur int SSL_set_cipher_list(SSL *s, const char *str); +__owur int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str); +__owur int SSL_set_ciphersuites(SSL *s, const char *str); void SSL_set_read_ahead(SSL *s, int yes); __owur int SSL_get_verify_mode(const SSL *s); __owur int SSL_get_verify_depth(const SSL *s); diff --git a/include/openssl/sslerr.h b/include/openssl/sslerr.h index 454877df85..77db8717cf 100644 --- a/include/openssl/sslerr.h +++ b/include/openssl/sslerr.h @@ -23,6 +23,7 @@ int ERR_load_SSL_strings(void); # define SSL_F_ADD_KEY_SHARE 512 # define SSL_F_BYTES_TO_CIPHER_LIST 519 # define SSL_F_CHECK_SUITEB_CIPHER_LIST 331 +# define SSL_F_CIPHERSUITE_CB 621 # define SSL_F_CONSTRUCT_CA_NAMES 552 # define SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS 553 # define SSL_F_CREATE_SYNTHETIC_MESSAGE_HASH 539 diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h index 0d5b9f8cba..b9f0918f3e 100644 --- a/include/openssl/tls1.h +++ b/include/openssl/tls1.h @@ -1131,18 +1131,6 @@ __owur int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain) # define TLS1_TXT_RSA_PSK_WITH_ARIA_128_GCM_SHA256 "RSA-PSK-ARIA128-GCM-SHA256" # define TLS1_TXT_RSA_PSK_WITH_ARIA_256_GCM_SHA384 "RSA-PSK-ARIA256-GCM-SHA384" - -/* TLSv1.3 ciphersuites */ -/* - * TODO(TLS1.3): Review the naming scheme for TLSv1.3 ciphers and also the - * cipherstring selection process for these ciphers - */ -# define TLS1_3_TXT_AES_128_GCM_SHA256 "TLS13-AES-128-GCM-SHA256" -# define TLS1_3_TXT_AES_256_GCM_SHA384 "TLS13-AES-256-GCM-SHA384" -# define TLS1_3_TXT_CHACHA20_POLY1305_SHA256 "TLS13-CHACHA20-POLY1305-SHA256" -# define TLS1_3_TXT_AES_128_CCM_SHA256 "TLS13-AES-128-CCM-SHA256" -# define TLS1_3_TXT_AES_128_CCM_8_SHA256 "TLS13-AES-128-CCM-8-SHA256" - # define TLS_CT_RSA_SIGN 1 # define TLS_CT_DSS_SIGN 2 # define TLS_CT_RSA_FIXED_DH 3 diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index 8f0d3e12d1..f230b5ff46 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -18,6 +18,7 @@ #include <openssl/rand.h> #include "internal/cryptlib.h" +#define TLS13_NUM_CIPHERS OSSL_NELEM(tls13_ciphers) #define SSL3_NUM_CIPHERS OSSL_NELEM(ssl3_ciphers) #define SSL3_NUM_SCSVS OSSL_NELEM(ssl3_scsvs) @@ -29,6 +30,90 @@ const unsigned char tls12downgrade[] = { 0x44, 0x4f, 0x57, 0x4e, 0x47, 0x52, 0x44, 0x01 }; +/* The list of available TLSv1.3 ciphers */ +static SSL_CIPHER tls13_ciphers[] = { + { + 1, + TLS1_3_RFC_AES_128_GCM_SHA256, + TLS1_3_RFC_AES_128_GCM_SHA256, + TLS1_3_CK_AES_128_GCM_SHA256, + 0, 0, + SSL_AES128GCM, + SSL_AEAD, + TLS1_3_VERSION, TLS1_3_VERSION, + SSL_kANY, + SSL_aANY, + SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256, + 128, + 128, + }, { + 1, + TLS1_3_RFC_AES_256_GCM_SHA384, + TLS1_3_RFC_AES_256_GCM_SHA384, + TLS1_3_CK_AES_256_GCM_SHA384, + SSL_kANY, + SSL_aANY, + SSL_AES256GCM, + SSL_AEAD, + TLS1_3_VERSION, TLS1_3_VERSION, + 0, 0, + SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA384, + 256, + 256, + }, +#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305) + { + 1, + TLS1_3_RFC_CHACHA20_POLY1305_SHA256, + TLS1_3_RFC_CHACHA20_POLY1305_SHA256, + TLS1_3_CK_CHACHA20_POLY1305_SHA256, + SSL_kANY, + SSL_aANY, + SSL_CHACHA20POLY1305, + SSL_AEAD, + TLS1_3_VERSION, TLS1_3_VERSION, + 0, 0, + SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256, + 256, + 256, + }, +#endif + { + 1, + TLS1_3_RFC_AES_128_CCM_SHA256, + TLS1_3_RFC_AES_128_CCM_SHA256, + TLS1_3_CK_AES_128_CCM_SHA256, + SSL_kANY, + SSL_aANY, + SSL_AES128CCM, + SSL_AEAD, + TLS1_3_VERSION, TLS1_3_VERSION, + 0, 0, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256, + 128, + 128, + }, { + 1, + TLS1_3_RFC_AES_128_CCM_8_SHA256, + TLS1_3_RFC_AES_128_CCM_8_SHA256, + TLS1_3_CK_AES_128_CCM_8_SHA256, + SSL_kANY, + SSL_aANY, + SSL_AES128CCM8, + SSL_AEAD, + TLS1_3_VERSION, TLS1_3_VERSION, + 0, 0, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256, + 128, + 128, + } +}; + /* * The list of available ciphers, mostly organized into the following * groups: @@ -860,88 +945,6 @@ static SSL_CIPHER ssl3_ciphers[] = { }, { 1, - TLS1_3_TXT_AES_128_GCM_SHA256, - TLS1_3_RFC_AES_128_GCM_SHA256, - TLS1_3_CK_AES_128_GCM_SHA256, - 0, 0, - SSL_AES128GCM, - SSL_AEAD, - TLS1_3_VERSION, TLS1_3_VERSION, - SSL_kANY, - SSL_aANY, - SSL_HIGH, - SSL_HANDSHAKE_MAC_SHA256, - 128, - 128, - }, - { - 1, - TLS1_3_TXT_AES_256_GCM_SHA384, - TLS1_3_RFC_AES_256_GCM_SHA384, - TLS1_3_CK_AES_256_GCM_SHA384, - SSL_kANY, - SSL_aANY, - SSL_AES256GCM, - SSL_AEAD, - TLS1_3_VERSION, TLS1_3_VERSION, - 0, 0, - SSL_HIGH, - SSL_HANDSHAKE_MAC_SHA384, - 256, - 256, - }, -#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305) - { - 1, - TLS1_3_TXT_CHACHA20_POLY1305_SHA256, - TLS1_3_RFC_CHACHA20_POLY1305_SHA256, - TLS1_3_CK_CHACHA20_POLY1305_SHA256, - SSL_kANY, - SSL_aANY, - SSL_CHACHA20POLY1305, - SSL_AEAD, - TLS1_3_VERSION, TLS1_3_VERSION, - 0, 0, - SSL_HIGH, - SSL_HANDSHAKE_MAC_SHA256, - 256, - 256, - }, -#endif - { - 1, - TLS1_3_TXT_AES_128_CCM_SHA256, - TLS1_3_RFC_AES_128_CCM_SHA256, - TLS1_3_CK_AES_128_CCM_SHA256, - SSL_kANY, - SSL_aANY, - SSL_AES128CCM, - SSL_AEAD, - TLS1_3_VERSION, TLS1_3_VERSION, - 0, 0, - SSL_NOT_DEFAULT | SSL_HIGH, - SSL_HANDSHAKE_MAC_SHA256, - 128, - 128, - }, - { - 1, - TLS1_3_TXT_AES_128_CCM_8_SHA256, - TLS1_3_RFC_AES_128_CCM_8_SHA256, - TLS1_3_CK_AES_128_CCM_8_SHA256, - SSL_kANY, - SSL_aANY, - SSL_AES128CCM8, - SSL_AEAD, - TLS1_3_VERSION, TLS1_3_VERSION, - 0, 0, - SSL_NOT_DEFAULT | SSL_HIGH, - SSL_HANDSHAKE_MAC_SHA256, - 128, - 128, - }, - { - 1, TLS1_TXT_ECDHE_ECDSA_WITH_NULL_SHA, TLS1_RFC_ECDHE_ECDSA_WITH_NULL_SHA, TLS1_CK_ECDHE_ECDSA_WITH_NULL_SHA, @@ -3207,6 +3210,8 @@ static int cipher_compare(const void *a, const void *b) void ssl_sort_cipher_list(void) { + qsort(tls13_ciphers, TLS13_NUM_CIPHERS, sizeof(tls13_ciphers[0]), + cipher_compare); qsort(ssl3_ciphers, SSL3_NUM_CIPHERS, sizeof(ssl3_ciphers[0]), cipher_compare); qsort(ssl3_scsvs, SSL3_NUM_SCSVS, sizeof(ssl3_scsvs[0]), cipher_compare); @@ -4027,6 +4032,9 @@ const SSL_CIPHER *ssl3_get_cipher_by_id(uint32_t id) const SSL_CIPHER *cp; c.id = id; + cp = OBJ_bsearch_ssl_cipher_id(&c, tls13_ciphers, TLS13_NUM_CIPHERS); + if (cp != NULL) + return cp; cp = OBJ_bsearch_ssl_cipher_id(&c, ssl3_ciphers, SSL3_NUM_CIPHERS); if (cp != NULL) return cp; @@ -4035,17 +4043,19 @@ const SSL_CIPHER *ssl3_get_cipher_by_id(uint32_t id) const SSL_CIPHER *ssl3_get_cipher_by_std_name(const char *stdname) { - SSL_CIPHER *c = NULL; - SSL_CIPHER *tbl = ssl3_ciphers; - size_t i; + SSL_CIPHER *c = NULL, *tbl; + SSL_CIPHER *alltabs[] = {tls13_ciphers, ssl3_ciphers}; + size_t i, j, tblsize[] = {TLS13_NUM_CIPHERS, SSL3_NUM_CIPHERS}; /* this is not efficient, necessary to optimize this? */ - for (i = 0; i < SSL3_NUM_CIPHERS; i++, tbl++) { - if (tbl->stdname == NULL) - continue; - if (strcmp(stdname, tbl->stdname) == 0) { - c = tbl; - break; + for (j = 0; j < OSSL_NELEM(alltabs); j++) { + for (i = 0, tbl = alltabs[j]; i < tblsize[j]; i++, tbl++) { + if (tbl->stdname == NULL) + continue; + if (strcmp(stdname, tbl->stdname) == 0) { + c = tbl; + break; + } } } if (c == NULL) { diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c index d31aeb7783..49e16fc695 100644 --- a/ssl/ssl_ciph.c +++ b/ssl/ssl_ciph.c @@ -1274,12 +1274,14 @@ static int check_suiteb_cipher_list(const SSL_METHOD *meth, CERT *c, } #endif -STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, STACK_OF(SSL_CIPHER) - **cipher_list, STACK_OF(SSL_CIPHER) - **cipher_list_by_id, - const char *rule_str, CERT *c) +STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, + STACK_OF(SSL_CIPHER) *tls13_ciphersuites, + STACK_OF(SSL_CIPHER) **cipher_list, + STACK_OF(SSL_CIPHER) **cipher_list_by_id, + const char *rule_str, + CERT *c) { - int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases; + int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases, i; uint32_t disabled_mkey, disabled_auth, disabled_enc, disabled_mac; STACK_OF(SSL_CIPHER) *cipherstack, *tmp_cipher_list; const char *rule_p; @@ -1469,6 +1471,15 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, STACK return NULL; } + /* Add TLSv1.3 ciphers first - we always prefer those if possible */ + for (i = 0; i < sk_SSL_CIPHER_num(tls13_ciphersuites); i++) { + if (!sk_SSL_CIPHER_push(cipherstack, + sk_SSL_CIPHER_value(tls13_ciphersuites, i))) { + sk_SSL_CIPHER_free(cipherstack); + return NULL; + } + } + /* * The cipher selection for the list is done. The ciphers are added * to the resulting precedence to the STACK_OF(SSL_CIPHER). diff --git a/ssl/ssl_conf.c b/ssl/ssl_conf.c index 2c50d19bd9..30e43d9b82 100644 --- a/ssl/ssl_conf.c +++ b/ssl/ssl_conf.c @@ -256,6 +256,7 @@ static int cmd_ECDHParameters(SSL_CONF_CTX *cctx, const char *value) static int cmd_CipherString(SSL_CONF_CTX *cctx, const char *value) { int rv = 1; + if (cctx->ctx) rv = SSL_CTX_set_cipher_list(cctx->ctx, value); if (cctx->ssl) @@ -263,6 +264,17 @@ static int cmd_CipherString(SSL_CONF_CTX *cctx, const char *value) return rv > 0; } +static int cmd_Ciphersuites(SSL_CONF_CTX *cctx, const char *value) +{ + int rv = 1; + + if (cctx->ctx) + rv = SSL_CTX_set_ciphersuites(cctx->ctx, value); + if (cctx->ssl) + rv = SSL_set_ciphersuites(cctx->ssl, value); + return rv > 0; +} + static int cmd_Protocol(SSL_CONF_CTX *cctx, const char *value) { static const ssl_flag_tbl ssl_protocol_list[] = { @@ -606,6 +618,7 @@ static const ssl_conf_cmd_tbl ssl_conf_cmds[] = { SSL_CONF_CMD_STRING(ECDHParameters, "named_curve", SSL_CONF_FLAG_SERVER), #endif SSL_CONF_CMD_STRING(CipherString, "cipher", 0), + SSL_CONF_CMD_STRING(Ciphersuites, "ciphersuites", 0), SSL_CONF_CMD_STRING(Protocol, NULL, 0), SSL_CONF_CMD_STRING(MinProtocol, "min_protocol", 0), SSL_CONF_CMD_STRING(MaxProtocol, "max_protocol", 0), diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c index e367a364bb..64580bb560 100644 --- a/ssl/ssl_err.c +++ b/ssl/ssl_err.c @@ -20,6 +20,7 @@ static const ERR_STRING_DATA SSL_str_functs[] = { "bytes_to_cipher_list"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_CHECK_SUITEB_CIPHER_LIST, 0), "check_suiteb_cipher_list"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_CIPHERSUITE_CB, 0), "ciphersuite_cb"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_CONSTRUCT_CA_NAMES, 0), "construct_ca_names"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS, 0), "construct_key_exchange_tbs"}, diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 0814fb362b..a4e7374969 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -653,7 +653,9 @@ int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth) ctx->method = meth; - sk = ssl_create_cipher_list(ctx->method, &(ctx->cipher_list), + sk = ssl_create_cipher_list(ctx->method, + ctx->tls13_ciphersuites, + &(ctx->cipher_list), &(ctx->cipher_list_by_id), SSL_DEFAULT_CIPHER_LIST, ctx->cert); if ((sk == NULL) || (sk_SSL_CIPHER_num(sk) <= 0)) { @@ -712,6 +714,11 @@ SSL *SSL_new(SSL_CTX *ctx) s->max_cert_list = ctx->max_cert_list; s->max_early_data = ctx->max_early_data; + /* Shallow copy of the ciphersuites stack */ + s->tls13_ciphersuites = sk_SSL_CIPHER_dup(ctx->tls13_ciphersuites); + if (s->tls13_ciphersuites == NULL) + goto err; + /* * Earlier library versions used to copy the pointer to the CERT, not * its contents; only when setting new parameters for the per-SSL @@ -1156,6 +1163,7 @@ void SSL_free(SSL *s) /* add extra stuff */ sk_SSL_CIPHER_free(s->cipher_list); sk_SSL_CIPHER_free(s->cipher_list_by_id); + sk_SSL_CIPHER_free(s->tls13_ciphersuites); /* Make the next call work :-) */ if (s->session != NULL) { @@ -2520,8 +2528,9 @@ 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); + sk = ssl_create_cipher_list(ctx->method, 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 @@ -2543,8 +2552,9 @@ 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); + sk = ssl_create_cipher_list(s->ctx->method, s->tls13_ciphersuites, + &s->cipher_list, &s->cipher_list_by_id, str, + s->cert); /* see comment in SSL_CTX_set_cipher_list */ if (sk == NULL) return 0; @@ -2555,6 +2565,99 @@ 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 *p; @@ -2915,7 +3018,15 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) if (ret->ctlog_store == NULL) goto err; #endif + + if (!SSL_CTX_set_ciphersuites(ret, + "TLS_AES_256_GCM_SHA384:" + "TLS_CHACHA20_POLY1305_SHA256:" + "TLS_AES_128_GCM_SHA256")) + goto err; + if (!ssl_create_cipher_list(ret->method, + ret->tls13_ciphersuites, &ret->cipher_list, &ret->cipher_list_by_id, SSL_DEFAULT_CIPHER_LIST, ret->cert) || sk_SSL_CIPHER_num(ret->cipher_list) <= 0) { @@ -3075,6 +3186,7 @@ void SSL_CTX_free(SSL_CTX *a) #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_pop_free(a->extra_certs, X509_free); diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index 246605c81e..4b8482aeb7 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -740,6 +740,8 @@ struct ssl_ctx_st { 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; /* @@ -1108,6 +1110,8 @@ struct ssl_st { /* crypto */ STACK_OF(SSL_CIPHER) *cipher_list; STACK_OF(SSL_CIPHER) *cipher_list_by_id; + /* TLSv1.3 specific ciphersuites */ + STACK_OF(SSL_CIPHER) *tls13_ciphersuites; /* * These are the ones being used, the ones in SSL_SESSION are the ones to * be 'copied' into these ones @@ -2198,10 +2202,10 @@ __owur int ssl_cipher_id_cmp(const SSL_CIPHER *a, const SSL_CIPHER *b); DECLARE_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER, ssl_cipher_id); __owur int ssl_cipher_ptr_id_cmp(const SSL_CIPHER *const *ap, const SSL_CIPHER *const *bp); -__owur STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *meth, - STACK_OF(SSL_CIPHER) **pref, - STACK_OF(SSL_CIPHER) - **sorted, +__owur STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, + STACK_OF(SSL_CIPHER) *tls13_ciphersuites, + STACK_OF(SSL_CIPHER) **cipher_list, + STACK_OF(SSL_CIPHER) **cipher_list_by_id, const char *rule_str, CERT *c); __owur int ssl_cache_cipherlist(SSL *s, PACKET *cipher_suites, int sslv2format); diff --git a/test/cipherlist_test.c b/test/cipherlist_test.c index 50e3027028..b224983a34 100644 --- a/test/cipherlist_test.c +++ b/test/cipherlist_test.c @@ -63,6 +63,13 @@ static CIPHERLIST_TEST_FIXTURE *set_up(const char *const test_case_name) * are currently broken and should be considered mission impossible in libssl. */ static const uint32_t default_ciphers_in_order[] = { +#ifndef OPENSSL_NO_TLS1_3 + TLS1_3_CK_AES_256_GCM_SHA384, +# if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305) + TLS1_3_CK_CHACHA20_POLY1305_SHA256, +# endif + TLS1_3_CK_AES_128_GCM_SHA256, +#endif #ifndef OPENSSL_NO_TLS1_2 # ifndef OPENSSL_NO_EC TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, @@ -127,13 +134,6 @@ static const uint32_t default_ciphers_in_order[] = { TLS1_CK_RSA_WITH_AES_256_GCM_SHA384, TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, #endif -#ifndef OPENSSL_NO_TLS1_3 - TLS1_3_CK_AES_256_GCM_SHA384, -# if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305) - TLS1_3_CK_CHACHA20_POLY1305_SHA256, -# endif - TLS1_3_CK_AES_128_GCM_SHA256, -#endif #ifndef OPENSSL_NO_TLS1_2 TLS1_CK_RSA_WITH_AES_256_SHA256, TLS1_CK_RSA_WITH_AES_128_SHA256, diff --git a/test/clienthellotest.c b/test/clienthellotest.c index 5cff519ead..45595d393a 100644 --- a/test/clienthellotest.c +++ b/test/clienthellotest.c @@ -97,8 +97,7 @@ static int test_client_hello(int currtest) * ClientHello is already going to be quite long. To avoid getting one * that is too long for this test we use a restricted ciphersuite list */ - if (!TEST_true(SSL_CTX_set_cipher_list(ctx, - "TLS13-AES-128-GCM-SHA256"))) + if (!TEST_true(SSL_CTX_set_cipher_list(ctx, ""))) goto end; /* Fall through */ case TEST_ADD_PADDING: diff --git a/test/fatalerrtest.c b/test/fatalerrtest.c index 23357351f5..85b11c84aa 100644 --- a/test/fatalerrtest.c +++ b/test/fatalerrtest.c @@ -38,6 +38,10 @@ static int test_fatalerr(void) */ if (!TEST_true(SSL_CTX_set_cipher_list(sctx, "AES128-SHA")) || !TEST_true(SSL_CTX_set_cipher_list(cctx, "AES256-SHA")) + || !TEST_true(SSL_CTX_set_ciphersuites(sctx, + "TLS_AES_128_GCM_SHA256")) + || !TEST_true(SSL_CTX_set_ciphersuites(cctx, + "TLS_AES_256_GCM_SHA384")) || !TEST_true(create_ssl_objects(sctx, cctx, &sssl, &cssl, NULL, NULL))) goto err; diff --git a/test/recipes/70-test_sslsigalgs.t b/test/recipes/70-test_sslsigalgs.t index c1d827208b..95af8a1913 100644 --- a/test/recipes/70-test_sslsigalgs.t +++ b/test/recipes/70-test_sslsigalgs.t @@ -116,7 +116,7 @@ SKIP: { # should succeed $proxy->clear(); $proxy->serverflags("-no_tls1_3"); - $proxy->ciphers("ECDHE-RSA-AES128-SHA:TLS13-AES-128-GCM-SHA256"); + $proxy->ciphers("ECDHE-RSA-AES128-SHA"); $proxy->filter(undef); $proxy->start(); ok(TLSProxy::Message->success |