diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 4b9e1d6f7dd27831c8da021f2b4fe1c27dbcc77a..5bd2fcf5d5d2fd777a34a322362f010469bf53d3 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -2508,6 +2508,26 @@ STACK_OF(SSL_CIPHER) *SSL_CTX_get_ciphers(const SSL_CTX *ctx) return NULL; } +/* + * Distinguish between ciphers controlled by set_ciphersuite() and + * set_cipher_list() when counting. + */ +static int cipher_list_tls12_num(STACK_OF(SSL_CIPHER) *sk) +{ + int i, num = 0; + const SSL_CIPHER *c; + + if (sk == NULL) + return 0; + for (i = 0; i < sk_SSL_CIPHER_num(sk); ++i) { + c = sk_SSL_CIPHER_value(sk, i); + if (c->min_tls >= TLS1_3_VERSION) + continue; + num++; + } + return num; +} + /** specify the ciphers to be used by default by the SSL_CTX */ int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) { @@ -2525,7 +2545,7 @@ int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) */ if (sk == NULL) return 0; - else if (sk_SSL_CIPHER_num(sk) == 0) { + else if (cipher_list_tls12_num(sk) == 0) { SSLerr(SSL_F_SSL_CTX_SET_CIPHER_LIST, SSL_R_NO_CIPHER_MATCH); return 0; } @@ -2543,7 +2563,7 @@ int SSL_set_cipher_list(SSL *s, const char *str) /* see comment in SSL_CTX_set_cipher_list */ if (sk == NULL) return 0; - else if (sk_SSL_CIPHER_num(sk) == 0) { + else if (cipher_list_tls12_num(sk) == 0) { SSLerr(SSL_F_SSL_SET_CIPHER_LIST, SSL_R_NO_CIPHER_MATCH); return 0; } diff --git a/test/cipherlist_test.c b/test/cipherlist_test.c index 5023c1c4875fa4afd1aed34f9203354a1664feaf..a22f60b9334fe57594cfa1057d63a5f853bce2ff 100644 --- a/test/cipherlist_test.c +++ b/test/cipherlist_test.c @@ -215,9 +215,44 @@ static int test_default_cipherlist_explicit(void) return result; } +/* SSL_CTX_set_cipher_list() should fail if it clears all TLSv1.2 ciphers. */ +static int test_default_cipherlist_clear(void) +{ + SETUP_CIPHERLIST_TEST_FIXTURE(); + SSL *s = NULL; + + if (fixture == NULL) + return 0; + + if (!TEST_int_eq(SSL_CTX_set_cipher_list(fixture->server, "no-such"), 0)) + goto end; + + if (!TEST_int_eq(ERR_GET_REASON(ERR_get_error()), SSL_R_NO_CIPHER_MATCH)) + goto end; + + s = SSL_new(fixture->client); + + if (!TEST_ptr(s)) + goto end; + + if (!TEST_int_eq(SSL_set_cipher_list(s, "no-such"), 0)) + goto end; + + if (!TEST_int_eq(ERR_GET_REASON(ERR_get_error()), + SSL_R_NO_CIPHER_MATCH)) + goto end; + + result = 1; +end: + SSL_free(s); + tear_down(fixture); + return result; +} + int setup_tests(void) { ADD_TEST(test_default_cipherlist_implicit); ADD_TEST(test_default_cipherlist_explicit); + ADD_TEST(test_default_cipherlist_clear); return 1; } diff --git a/test/clienthellotest.c b/test/clienthellotest.c index 10e3b1b1b172408e7fffcbb893d5c4453cc3d44d..1045dd60ab2b316643f06a8fd1fffc7913f933a1 100644 --- a/test/clienthellotest.c +++ b/test/clienthellotest.c @@ -99,8 +99,9 @@ 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, ""))) + if (!TEST_false(SSL_CTX_set_cipher_list(ctx, ""))) goto end; + ERR_clear_error(); /* Fall through */ case TEST_ADD_PADDING: case TEST_PADDING_NOT_NEEDED: diff --git a/test/ssltest_old.c b/test/ssltest_old.c index 92970776fdda87811caedf61344715775efe5ccf..372035a1f0f0f0e8dcd82b381044f5091dc5f5db 100644 --- a/test/ssltest_old.c +++ b/test/ssltest_old.c @@ -1382,11 +1382,52 @@ int main(int argc, char *argv[]) goto end; if (cipher != NULL) { - if (!SSL_CTX_set_cipher_list(c_ctx, cipher) - || !SSL_CTX_set_cipher_list(s_ctx, cipher) - || !SSL_CTX_set_cipher_list(s_ctx2, cipher)) { - ERR_print_errors(bio_err); - goto end; + if (strcmp(cipher, "") == 0) { + if (!SSL_CTX_set_cipher_list(c_ctx, cipher)) { + if (ERR_GET_REASON(ERR_peek_error()) == SSL_R_NO_CIPHER_MATCH) { + ERR_clear_error(); + } else { + ERR_print_errors(bio_err); + goto end; + } + } else { + /* Should have failed when clearing all TLSv1.2 ciphers. */ + fprintf(stderr, "CLEARING ALL TLSv1.2 CIPHERS SHOULD FAIL\n"); + goto end; + } + + if (!SSL_CTX_set_cipher_list(s_ctx, cipher)) { + if (ERR_GET_REASON(ERR_peek_error()) == SSL_R_NO_CIPHER_MATCH) { + ERR_clear_error(); + } else { + ERR_print_errors(bio_err); + goto end; + } + } else { + /* Should have failed when clearing all TLSv1.2 ciphers. */ + fprintf(stderr, "CLEARING ALL TLSv1.2 CIPHERS SHOULD FAIL\n"); + goto end; + } + + if (!SSL_CTX_set_cipher_list(s_ctx2, cipher)) { + if (ERR_GET_REASON(ERR_peek_error()) == SSL_R_NO_CIPHER_MATCH) { + ERR_clear_error(); + } else { + ERR_print_errors(bio_err); + goto end; + } + } else { + /* Should have failed when clearing all TLSv1.2 ciphers. */ + fprintf(stderr, "CLEARING ALL TLSv1.2 CIPHERS SHOULD FAIL\n"); + goto end; + } + } else { + if (!SSL_CTX_set_cipher_list(c_ctx, cipher) + || !SSL_CTX_set_cipher_list(s_ctx, cipher) + || !SSL_CTX_set_cipher_list(s_ctx2, cipher)) { + ERR_print_errors(bio_err); + goto end; + } } } if (ciphersuites != NULL) {