X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=test%2Fsslapitest.c;h=181d0ef686fd4d8ecd33bb27ccacac70c7b57a03;hp=42417918c8ce970711c698ab47d652952425c2fa;hb=HEAD;hpb=4032cd9a1434610e4dc2bbde01f98d04faa615e5 diff --git a/test/sslapitest.c b/test/sslapitest.c index 42417918c8..31ba451117 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -39,6 +39,7 @@ #include "testutil.h" #include "testutil/output.h" #include "internal/nelem.h" +#include "internal/tlsgroups.h" #include "internal/ktls.h" #include "../ssl/ssl_local.h" #include "../ssl/record/methods/recmethod_local.h" @@ -77,8 +78,6 @@ static int find_session_cb(SSL *ssl, const unsigned char *identity, static int use_session_cb_cnt = 0; static int find_session_cb_cnt = 0; - -static SSL_SESSION *create_a_psk(SSL *ssl, size_t mdsize); #endif static char *certsdir = NULL; @@ -117,7 +116,6 @@ static int cdummyarg = 1; static X509 *ocspcert = NULL; #endif -#define NUM_EXTRA_CERTS 40 #define CLIENT_VERSION_LEN 2 /* @@ -715,14 +713,14 @@ static int full_client_hello_callback(SSL *s, int *al, void *arg) int *ctr = arg; const unsigned char *p; int *exts; - /* We only configure two ciphers, but the SCSV is added automatically. */ #ifdef OPENSSL_NO_EC - const unsigned char expected_ciphers[] = {0x00, 0x9d, 0x00, 0xff}; + const unsigned char expected_ciphers[] = {0x00, 0x9d}; #else const unsigned char expected_ciphers[] = {0x00, 0x9d, 0xc0, - 0x2c, 0x00, 0xff}; + 0x2c}; #endif const int expected_extensions[] = { + 65281, #ifndef OPENSSL_NO_EC 11, 10, #endif @@ -816,7 +814,7 @@ static int test_no_ems(void) status = create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE); if (fips_ems_check) { if (status == 1) { - printf("When FIPS uses the EMS check a connection that doesnt use EMS should fail\n"); + printf("When FIPS uses the EMS check a connection that doesn't use EMS should fail\n"); goto end; } } else { @@ -964,21 +962,6 @@ static int execute_test_large_message(const SSL_METHOD *smeth, SSL_CTX *cctx = NULL, *sctx = NULL; SSL *clientssl = NULL, *serverssl = NULL; int testresult = 0; - int i; - BIO *certbio = NULL; - X509 *chaincert = NULL; - int certlen; - - if (!TEST_ptr(certbio = BIO_new_file(cert, "r"))) - goto end; - - if (!TEST_ptr(chaincert = X509_new_ex(libctx, NULL))) - goto end; - - if (PEM_read_bio_X509(certbio, &chaincert, NULL, NULL) == NULL) - goto end; - BIO_free(certbio); - certbio = NULL; if (!TEST_true(create_ssl_ctx_pair(libctx, smeth, cmeth, min_version, max_version, &sctx, &cctx, cert, @@ -1006,24 +989,8 @@ static int execute_test_large_message(const SSL_METHOD *smeth, SSL_CTX_set_read_ahead(cctx, 1); } - /* - * We assume the supplied certificate is big enough so that if we add - * NUM_EXTRA_CERTS it will make the overall message large enough. The - * default buffer size is requested to be 16k, but due to the way BUF_MEM - * works, it ends up allocating a little over 21k (16 * 4/3). So, in this - * test we need to have a message larger than that. - */ - certlen = i2d_X509(chaincert, NULL); - OPENSSL_assert(certlen * NUM_EXTRA_CERTS > - (SSL3_RT_MAX_PLAIN_LENGTH * 4) / 3); - for (i = 0; i < NUM_EXTRA_CERTS; i++) { - if (!X509_up_ref(chaincert)) - goto end; - if (!SSL_CTX_add_extra_chain_cert(sctx, chaincert)) { - X509_free(chaincert); - goto end; - } - } + if (!ssl_ctx_add_large_cert_chain(libctx, sctx, cert)) + goto end; if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL)) @@ -1040,8 +1007,6 @@ static int execute_test_large_message(const SSL_METHOD *smeth, testresult = 1; end: - BIO_free(certbio); - X509_free(chaincert); SSL_free(serverssl); SSL_free(clientssl); SSL_CTX_free(sctx); @@ -1171,6 +1136,10 @@ static int execute_test_ktls(int cis_ktls, int sis_ktls, int cfd = -1, sfd = -1; int rx_supported; SSL_CONNECTION *clientsc, *serversc; + unsigned char *buf = NULL; + const size_t bufsz = SSL3_RT_MAX_PLAIN_LENGTH + 16; + int ret; + size_t offset = 0, i; if (!TEST_true(create_test_sockets(&cfd, &sfd, SOCK_STREAM, NULL))) goto end; @@ -1276,8 +1245,39 @@ static int execute_test_ktls(int cis_ktls, int sis_ktls, if (!TEST_true(ping_pong_query(clientssl, serverssl))) goto end; + buf = OPENSSL_zalloc(bufsz); + if (!TEST_ptr(buf)) + goto end; + + /* + * Write some data that exceeds the maximum record length. KTLS may choose + * to coalesce this data into a single buffer when we read it again. + */ + while ((ret = SSL_write(clientssl, buf, bufsz)) != (int)bufsz) { + if (!TEST_true(SSL_get_error(clientssl, ret) == SSL_ERROR_WANT_WRITE)) + goto end; + } + + /* Now check that we can read all the data we wrote */ + do { + ret = SSL_read(serverssl, buf + offset, bufsz - offset); + if (ret <= 0) { + if (!TEST_true(SSL_get_error(serverssl, ret) == SSL_ERROR_WANT_READ)) + goto end; + } else { + offset += ret; + } + } while (offset < bufsz); + + if (!TEST_true(offset == bufsz)) + goto end; + for (i = 0; i < bufsz; i++) + if (!TEST_true(buf[i] == 0)) + goto end; + testresult = 1; end: + OPENSSL_free(buf); if (clientssl) { SSL_shutdown(clientssl); SSL_free(clientssl); @@ -1700,6 +1700,8 @@ end: return testresult; } +#if !defined(OPENSSL_NO_TLS1_2) || !defined(OSSL_NO_USABLE_TLS1_3) \ + || !defined(OPENSSL_NO_DTLS) static int execute_cleanse_plaintext(const SSL_METHOD *smeth, const SSL_METHOD *cmeth, int min_version, int max_version) @@ -1722,15 +1724,13 @@ static int execute_cleanse_plaintext(const SSL_METHOD *smeth, privkey))) goto end; -#ifdef OPENSSL_NO_DTLS1_2 - if (smeth == DTLS_server_method()) { # ifdef OPENSSL_NO_DTLS1_2 + if (smeth == DTLS_server_method()) { /* Not supported in the FIPS provider */ if (is_fips) { testresult = 1; goto end; }; -# endif /* * Default sigalgs are SHA1 based in = 0) + res = TEST_skip("Test took too long, ignoring result"); + + return res; +} + static int test_early_data_read_write(int idx) { SSL_CTX *cctx = NULL, *sctx = NULL; @@ -3555,6 +3539,7 @@ static int test_early_data_read_write(int idx) unsigned char buf[20], data[1024]; size_t readbytes, written, eoedlen, rawread, rawwritten; BIO *rbio; + OSSL_TIME timer; /* Artificially give the next 2 tickets some age for non PSK sessions */ if (idx != 2) @@ -3568,13 +3553,20 @@ static int test_early_data_read_write(int idx) artificial_ticket_time = 0; /* Write and read some early data */ + timer = ossl_time_now(); if (!TEST_true(SSL_write_early_data(clientssl, MSG1, strlen(MSG1), &written)) - || !TEST_size_t_eq(written, strlen(MSG1)) - || !TEST_int_eq(SSL_read_early_data(serverssl, buf, - sizeof(buf), &readbytes), - SSL_READ_EARLY_DATA_SUCCESS) - || !TEST_mem_eq(MSG1, readbytes, buf, strlen(MSG1)) + || !TEST_size_t_eq(written, strlen(MSG1))) + goto end; + + if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf), + &readbytes), + SSL_READ_EARLY_DATA_SUCCESS)) { + testresult = check_early_data_timeout(timer); + goto end; + } + + if (!TEST_mem_eq(MSG1, readbytes, buf, strlen(MSG1)) || !TEST_int_eq(SSL_get_early_data_status(serverssl), SSL_EARLY_DATA_ACCEPTED)) goto end; @@ -3791,6 +3783,7 @@ static int test_early_data_replay_int(int idx, int usecb, int confopt) SSL_SESSION *sess = NULL; size_t readbytes, written; unsigned char buf[20]; + OSSL_TIME timer; allow_ed_cb_called = 0; @@ -3845,6 +3838,7 @@ static int test_early_data_replay_int(int idx, int usecb, int confopt) goto end; /* Write and read some early data */ + timer = ossl_time_now(); if (!TEST_true(SSL_write_early_data(clientssl, MSG1, strlen(MSG1), &written)) || !TEST_size_t_eq(written, strlen(MSG1))) @@ -3865,8 +3859,11 @@ static int test_early_data_replay_int(int idx, int usecb, int confopt) /* In this case the callback decides to accept the early data */ if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf), &readbytes), - SSL_READ_EARLY_DATA_SUCCESS) - || !TEST_mem_eq(MSG1, strlen(MSG1), buf, readbytes) + SSL_READ_EARLY_DATA_SUCCESS)) { + testresult = check_early_data_timeout(timer); + goto end; + } + if (!TEST_mem_eq(MSG1, strlen(MSG1), buf, readbytes) /* * Server will have sent its flight so client can now send * end of early data and complete its half of the handshake @@ -3918,7 +3915,13 @@ static const char *ciphersuites[] = { "TLS_AES_256_GCM_SHA384", "TLS_AES_128_CCM_SHA256", #if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305) - "TLS_CHACHA20_POLY1305_SHA256" + "TLS_CHACHA20_POLY1305_SHA256", +#else + NULL, +#endif +#if !defined(OPENSSL_NO_INTEGRITY_ONLY_CIPHERS) + "TLS_SHA256_SHA256", + "TLS_SHA384_SHA384" #endif }; @@ -3939,16 +3942,19 @@ static int early_data_skip_helper(int testtype, int cipher, int idx) unsigned char buf[20]; size_t readbytes, written; - if (is_fips && cipher == 4) + if (is_fips && cipher >= 4) return 1; + if (ciphersuites[cipher] == NULL) + return TEST_skip("Cipher not supported"); + if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), TLS_client_method(), TLS1_VERSION, 0, &sctx, &cctx, cert, privkey))) goto end; - if (cipher == 0) { + if (cipher == 0 || cipher == 5 || cipher == 6) { SSL_CTX_set_security_level(sctx, 0); SSL_CTX_set_security_level(cctx, 0); } @@ -3959,8 +3965,9 @@ static int early_data_skip_helper(int testtype, int cipher, int idx) if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl, &serverssl, &sess, idx, - cipher == 2 ? SHA384_DIGEST_LENGTH - : SHA256_DIGEST_LENGTH))) + (cipher == 2 || cipher == 6) + ? SHA384_DIGEST_LENGTH + : SHA256_DIGEST_LENGTH))) goto end; if (testtype == 1 || testtype == 2) { @@ -4383,13 +4390,19 @@ static int test_early_data_psk(int idx) || !TEST_int_eq(ERR_GET_REASON(ERR_get_error()), err)) goto end; } else { + OSSL_TIME timer = ossl_time_now(); + if (!TEST_true(SSL_write_early_data(clientssl, MSG1, strlen(MSG1), &written))) goto end; if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf), - &readbytes), readearlyres) - || (readearlyres == SSL_READ_EARLY_DATA_SUCCESS + &readbytes), readearlyres)) { + testresult = check_early_data_timeout(timer); + goto end; + } + + if ((readearlyres == SSL_READ_EARLY_DATA_SUCCESS && !TEST_mem_eq(buf, readbytes, MSG1, strlen(MSG1))) || !TEST_int_eq(SSL_get_early_data_status(serverssl), edstatus) || !TEST_int_eq(SSL_connect(clientssl), connectres)) @@ -4411,12 +4424,14 @@ static int test_early_data_psk(int idx) } /* - * Test TLSv1.3 PSK can be used to send early_data with all 5 ciphersuites + * Test TLSv1.3 PSK can be used to send early_data with all 7 ciphersuites * idx == 0: Test with TLS1_3_RFC_AES_128_GCM_SHA256 * idx == 1: Test with TLS1_3_RFC_AES_256_GCM_SHA384 * idx == 2: Test with TLS1_3_RFC_CHACHA20_POLY1305_SHA256, * idx == 3: Test with TLS1_3_RFC_AES_128_CCM_SHA256 * idx == 4: Test with TLS1_3_RFC_AES_128_CCM_8_SHA256 + * idx == 5: Test with TLS1_3_RFC_SHA256_SHA256 + * idx == 6: Test with TLS1_3_RFC_SHA384_SHA384 */ static int test_early_data_psk_with_all_ciphers(int idx) { @@ -4427,6 +4442,7 @@ static int test_early_data_psk_with_all_ciphers(int idx) unsigned char buf[20]; size_t readbytes, written; const SSL_CIPHER *cipher; + OSSL_TIME timer; const char *cipher_str[] = { TLS1_3_RFC_AES_128_GCM_SHA256, TLS1_3_RFC_AES_256_GCM_SHA384, @@ -4436,7 +4452,14 @@ static int test_early_data_psk_with_all_ciphers(int idx) NULL, # endif TLS1_3_RFC_AES_128_CCM_SHA256, - TLS1_3_RFC_AES_128_CCM_8_SHA256 + TLS1_3_RFC_AES_128_CCM_8_SHA256, +# if !defined(OPENSSL_NO_INTEGRITY_ONLY_CIPHERS) + TLS1_3_RFC_SHA256_SHA256, + TLS1_3_RFC_SHA384_SHA384 +#else + NULL, + NULL +#endif }; const unsigned char *cipher_bytes[] = { TLS13_AES_128_GCM_SHA256_BYTES, @@ -4447,13 +4470,23 @@ static int test_early_data_psk_with_all_ciphers(int idx) NULL, # endif TLS13_AES_128_CCM_SHA256_BYTES, - TLS13_AES_128_CCM_8_SHA256_BYTES + TLS13_AES_128_CCM_8_SHA256_BYTES, +# if !defined(OPENSSL_NO_INTEGRITY_ONLY_CIPHERS) + TLS13_SHA256_SHA256_BYTES, + TLS13_SHA384_SHA384_BYTES +#else + NULL, + NULL +#endif }; if (cipher_str[idx] == NULL) return 1; - /* Skip ChaCha20Poly1305 as currently FIPS module does not support it */ - if (idx == 2 && is_fips == 1) + /* + * Skip ChaCha20Poly1305 and TLS_SHA{256,384}_SHA{256,384} ciphers + * as currently FIPS module does not support them. + */ + if ((idx == 2 || idx == 5 || idx == 6) && is_fips == 1) return 1; /* We always set this up with a final parameter of "2" for PSK */ @@ -4462,8 +4495,11 @@ static int test_early_data_psk_with_all_ciphers(int idx) SHA384_DIGEST_LENGTH))) goto end; - if (idx == 4) { - /* CCM8 ciphers are considered low security due to their short tag */ + if (idx == 4 || idx == 5 || idx == 6) { + /* + * CCM8 ciphers are considered low security due to their short tag. + * Integrity-only cipher do not provide any confidentiality. + */ SSL_set_security_level(clientssl, 0); SSL_set_security_level(serverssl, 0); } @@ -4484,14 +4520,19 @@ static int test_early_data_psk_with_all_ciphers(int idx) goto end; SSL_set_connect_state(clientssl); + timer = ossl_time_now(); if (!TEST_true(SSL_write_early_data(clientssl, MSG1, strlen(MSG1), &written))) goto end; if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf), &readbytes), - SSL_READ_EARLY_DATA_SUCCESS) - || !TEST_mem_eq(buf, readbytes, MSG1, strlen(MSG1)) + SSL_READ_EARLY_DATA_SUCCESS)) { + testresult = check_early_data_timeout(timer); + goto end; + } + + if (!TEST_mem_eq(buf, readbytes, MSG1, strlen(MSG1)) || !TEST_int_eq(SSL_get_early_data_status(serverssl), SSL_EARLY_DATA_ACCEPTED) || !TEST_int_eq(SSL_connect(clientssl), 1) @@ -4939,10 +4980,14 @@ static int test_key_exchange(int idx) break; # ifndef OPENSSL_NO_ECX case 4: + if (is_fips) + return TEST_skip("X25519 might not be supported by fips provider."); kexch_alg = NID_X25519; kexch_name0 = "x25519"; break; case 5: + if (is_fips) + return TEST_skip("X448 might not be supported by fips provider."); kexch_alg = NID_X448; kexch_name0 = "x448"; break; @@ -5161,6 +5206,9 @@ static int test_negotiated_group(int idx) else expectednid = kexch_alg; + if (is_fips && (kexch_alg == NID_X25519 || kexch_alg == NID_X448)) + return TEST_skip("X25519 and X448 might not be available in fips provider."); + if (!istls13) max_version = TLS1_2_VERSION; @@ -5309,7 +5357,12 @@ static int test_tls13_ciphersuite(int idx) # endif /* CCM8 ciphers are considered low security due to their short tag */ { TLS1_3_RFC_AES_128_CCM_8_SHA256 - ":" TLS1_3_RFC_AES_128_CCM_SHA256, 1, 1 } + ":" TLS1_3_RFC_AES_128_CCM_SHA256, 1, 1 }, +# if !defined(OPENSSL_NO_INTEGRITY_ONLY_CIPHERS) + /* Integrity-only cipher do not provide any confidentiality */ + { TLS1_3_RFC_SHA256_SHA256, 0, 1 }, + { TLS1_3_RFC_SHA384_SHA384, 0, 1 } +# endif }; const char *t13_cipher = NULL; const char *t12_cipher = NULL; @@ -5670,6 +5723,119 @@ static int test_tls13_psk(int idx) return testresult; } +#ifndef OSSL_NO_USABLE_TLS1_3 +/* + * Test TLS1.3 connection establishment succeeds with various configurations of + * the options `SSL_OP_ALLOW_NO_DHE_KEX` and `SSL_OP_PREFER_NO_DHE_KEX`. + * The verification of whether the right KEX mode is chosen is not covered by + * this test but by `test_tls13kexmodes`. + * + * Tests (idx & 1): Server has `SSL_OP_ALLOW_NO_DHE_KEX` set. + * Tests (idx & 2): Server has `SSL_OP_PREFER_NO_DHE_KEX` set. + * Tests (idx & 4): Client has `SSL_OP_ALLOW_NO_DHE_KEX` set. + */ +static int test_tls13_no_dhe_kex(const int idx) +{ + SSL_CTX *sctx = NULL, *cctx = NULL; + SSL *serverssl = NULL, *clientssl = NULL; + int testresult = 0; + size_t j; + SSL_SESSION *saved_session; + + int server_allow_no_dhe = (idx & 1) != 0; + int server_prefer_no_dhe = (idx & 2) != 0; + int client_allow_no_dhe = (idx & 4) != 0; + + uint64_t server_options = 0 + | (server_allow_no_dhe ? SSL_OP_ALLOW_NO_DHE_KEX : 0) + | (server_prefer_no_dhe ? SSL_OP_PREFER_NO_DHE_KEX : 0); + + uint64_t client_options = 0 + | (client_allow_no_dhe ? SSL_OP_ALLOW_NO_DHE_KEX : 0); + + new_called = 0; + do_cache = 1; + + if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), + TLS_client_method(), TLS1_3_VERSION, 0, + &sctx, &cctx, cert, privkey))) + goto end; + + SSL_CTX_set_session_cache_mode(cctx, SSL_SESS_CACHE_CLIENT + | SSL_SESS_CACHE_NO_INTERNAL_STORE); + + SSL_CTX_set_options(sctx, server_options); + SSL_CTX_set_options(cctx, client_options); + + SSL_CTX_sess_set_new_cb(cctx, new_cachesession_cb); + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, + &clientssl, NULL, NULL))) + goto end; + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE)) + /* Check we got the number of tickets we were expecting */ + || !TEST_int_eq(2, new_called)) + goto end; + + /* We'll reuse the last ticket. */ + saved_session = sesscache[new_called - 1]; + + SSL_shutdown(clientssl); + SSL_shutdown(serverssl); + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(cctx); + clientssl = serverssl = NULL; + cctx = NULL; + + /* + * Now we resume with the last ticket we created. + */ + + /* The server context already exists, so we only create the client. */ + if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), + TLS_client_method(), TLS1_3_VERSION, 0, + NULL, &cctx, cert, privkey))) + goto end; + + SSL_CTX_set_options(cctx, client_options); + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, + &clientssl, NULL, NULL)) + || !TEST_true(SSL_set_session(clientssl, saved_session))) + goto end; + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE))) + goto end; + + /* + * Make sure, the session was resumed. + */ + if (!TEST_true(SSL_session_reused(clientssl))) + goto end; + + SSL_shutdown(clientssl); + SSL_shutdown(serverssl); + + testresult = 1; + + end: + SSL_free(serverssl); + SSL_free(clientssl); + for (j = 0; j < OSSL_NELEM(sesscache); j++) { + SSL_SESSION_free(sesscache[j]); + sesscache[j] = NULL; + } + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + + return testresult; +} +#endif /* OSSL_NO_USABLE_TLS1_3 */ + static unsigned char cookie_magic_value[] = "cookie magic"; static int generate_cookie_callback(SSL *ssl, unsigned char *cookie, @@ -6298,8 +6464,10 @@ static int test_export_key_mat(int tst) const char label[LONG_LABEL_LEN + 1] = "test label"; const unsigned char context[] = "context"; const unsigned char *emptycontext = NULL; - unsigned char ckeymat1[80], ckeymat2[80], ckeymat3[80]; - unsigned char skeymat1[80], skeymat2[80], skeymat3[80]; + unsigned char longcontext[1280]; + int test_longcontext = fips_provider_version_ge(libctx, 3, 3, 0); + unsigned char ckeymat1[80], ckeymat2[80], ckeymat3[80], ckeymat4[80]; + unsigned char skeymat1[80], skeymat2[80], skeymat3[80], skeymat4[80]; size_t labellen; const int protocols[] = { TLS1_VERSION, @@ -6377,6 +6545,8 @@ static int test_export_key_mat(int tst) labellen = SMALL_LABEL_LEN; } + memset(longcontext, 1, sizeof(longcontext)); + if (!TEST_int_eq(SSL_export_keying_material(clientssl, ckeymat1, sizeof(ckeymat1), label, labellen, context, @@ -6390,6 +6560,14 @@ static int test_export_key_mat(int tst) sizeof(ckeymat3), label, labellen, NULL, 0, 0), 1) + || (test_longcontext + && !TEST_int_eq(SSL_export_keying_material(clientssl, + ckeymat4, + sizeof(ckeymat4), label, + labellen, + longcontext, + sizeof(longcontext), 1), + 1)) || !TEST_int_eq(SSL_export_keying_material(serverssl, skeymat1, sizeof(skeymat1), label, labellen, @@ -6405,6 +6583,13 @@ static int test_export_key_mat(int tst) sizeof(skeymat3), label, labellen, NULL, 0, 0), 1) + || (test_longcontext + && !TEST_int_eq(SSL_export_keying_material(serverssl, skeymat4, + sizeof(skeymat4), label, + labellen, + longcontext, + sizeof(longcontext), 1), + 1)) /* * Check that both sides created the same key material with the * same context. @@ -6423,6 +6608,13 @@ static int test_export_key_mat(int tst) */ || !TEST_mem_eq(ckeymat3, sizeof(ckeymat3), skeymat3, sizeof(skeymat3)) + /* + * Check that both sides created the same key material with a + * long context. + */ + || (test_longcontext + && !TEST_mem_eq(ckeymat4, sizeof(ckeymat4), skeymat4, + sizeof(skeymat4))) /* Different contexts should produce different results */ || !TEST_mem_ne(ckeymat1, sizeof(ckeymat1), ckeymat2, sizeof(ckeymat2))) @@ -6632,7 +6824,9 @@ static int test_key_update_peer_in_write(int tst) /* Write data that we know will fail with SSL_ERROR_WANT_WRITE */ if (!TEST_int_eq(SSL_write(peerwrite, mess, strlen(mess)), -1) - || !TEST_int_eq(SSL_get_error(peerwrite, 0), SSL_ERROR_WANT_WRITE)) + || !TEST_int_eq(SSL_get_error(peerwrite, 0), SSL_ERROR_WANT_WRITE) + || !TEST_true(SSL_want_write(peerwrite)) + || !TEST_true(SSL_net_write_desired(peerwrite))) goto end; /* Reinstate the original writing endpoint's write BIO */ @@ -6641,7 +6835,9 @@ static int test_key_update_peer_in_write(int tst) /* Now read some data - we will read the key update */ if (!TEST_int_eq(SSL_read(peerwrite, buf, sizeof(buf)), -1) - || !TEST_int_eq(SSL_get_error(peerwrite, 0), SSL_ERROR_WANT_READ)) + || !TEST_int_eq(SSL_get_error(peerwrite, 0), SSL_ERROR_WANT_READ) + || !TEST_true(SSL_want_read(peerwrite)) + || !TEST_true(SSL_net_read_desired(peerwrite))) goto end; /* @@ -6657,6 +6853,11 @@ static int test_key_update_peer_in_write(int tst) || !TEST_int_eq(SSL_read(peerupdate, buf, sizeof(buf)), strlen(mess))) goto end; + if (!TEST_false(SSL_net_read_desired(peerwrite)) + || !TEST_false(SSL_net_write_desired(peerwrite)) + || !TEST_int_eq(SSL_want(peerwrite), SSL_NOTHING)) + goto end; + testresult = 1; end: @@ -6929,22 +7130,45 @@ static int test_key_update_local_in_read(int tst) } #endif /* OSSL_NO_USABLE_TLS1_3 */ +/* + * Test clearing a connection via SSL_clear(), or resetting it via + * SSL_set_connect_state()/SSL_set_accept_state() + * Test 0: SSL_set_connect_state, TLSv1.3 + * Test 1: SSL_set_connect_state, TLSv1.2 + * Test 2: SSL_set_accept_state, TLSv1.3 + * Test 3: SSL_set_accept_state, TLSv1.2 + * Test 4: SSL_clear (client), TLSv1.3 + * Test 5: SSL_clear (client), TLSv1.2 + * Test 6: SSL_clear (server), TLSv1.3 + * Test 7: SSL_clear (server), TLSv1.2 + */ static int test_ssl_clear(int idx) { SSL_CTX *cctx = NULL, *sctx = NULL; SSL *clientssl = NULL, *serverssl = NULL; + SSL *writer, *reader; int testresult = 0; + int tls12test, servertest, cleartest; + size_t written, readbytes; + const char *msg = "Hello World"; + unsigned char buf[5]; + + tls12test = idx & 1; + idx >>= 1; + servertest = idx & 1; + idx >>= 1; + cleartest = idx & 1; #ifdef OPENSSL_NO_TLS1_2 - if (idx == 1) - return 1; + if (tls12test == 1) + return TEST_skip("No TLSv1.2 in this build"); #endif /* Create an initial connection */ if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), TLS_client_method(), TLS1_VERSION, 0, &sctx, &cctx, cert, privkey)) - || (idx == 1 + || (tls12test && !TEST_true(SSL_CTX_set_max_proto_version(cctx, TLS1_2_VERSION))) || !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, @@ -6953,20 +7177,68 @@ static int test_ssl_clear(int idx) SSL_ERROR_NONE))) goto end; + if (servertest) { + writer = clientssl; + reader = serverssl; + } else { + writer = serverssl; + reader = clientssl; + } + + /* Write some data */ + if (!TEST_true(SSL_write_ex(writer, msg, strlen(msg), &written)) + || written != strlen(msg)) + goto end; + + /* + * Read a partial record. The remaining buffered data should be cleared by + * the subsequent clear/reset + */ + if (!TEST_true(SSL_read_ex(reader, buf, sizeof(buf), &readbytes)) + || readbytes != sizeof(buf)) + goto end; + SSL_shutdown(clientssl); SSL_shutdown(serverssl); - SSL_free(serverssl); - serverssl = NULL; - /* Clear clientssl - we're going to reuse the object */ - if (!TEST_true(SSL_clear(clientssl))) - goto end; + /* Reset/clear one SSL object in order to reuse it. We free the other one */ + if (servertest) { + if (cleartest) { + if (!TEST_true(SSL_clear(serverssl))) + goto end; + } else { + SSL_set_accept_state(serverssl); + } + /* + * A peculiarity of SSL_clear() is that it does not clear the session. + * This is intended behaviour so that a client can create a new + * connection and reuse the session. But this doesn't make much sense + * on the server side - and causes incorrect behaviour due to the + * handshake failing (even though the documentation does say SSL_clear() + * is supposed to work on the server side). We clear the session + * explicitly - although note that the documentation for + * SSL_set_session() says that its only useful for clients! + */ + if (!TEST_true(SSL_set_session(serverssl, NULL))) + goto end; + SSL_free(clientssl); + clientssl = NULL; + } else { + if (cleartest) { + if (!TEST_true(SSL_clear(clientssl))) + goto end; + } else { + SSL_set_connect_state(clientssl); + } + SSL_free(serverssl); + serverssl = NULL; + } if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL)) || !TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)) - || !TEST_true(SSL_session_reused(clientssl))) + || !TEST_true(servertest || SSL_session_reused(clientssl))) goto end; SSL_shutdown(clientssl); @@ -7588,6 +7860,7 @@ static int test_info_callback(int tst) SSL_SESSION *sess = NULL; size_t written, readbytes; unsigned char buf[80]; + OSSL_TIME timer; /* early_data tests */ if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl, @@ -7602,13 +7875,20 @@ static int test_info_callback(int tst) sslapi_info_callback); /* Write and read some early data and then complete the connection */ + timer = ossl_time_now(); if (!TEST_true(SSL_write_early_data(clientssl, MSG1, strlen(MSG1), &written)) - || !TEST_size_t_eq(written, strlen(MSG1)) - || !TEST_int_eq(SSL_read_early_data(serverssl, buf, - sizeof(buf), &readbytes), - SSL_READ_EARLY_DATA_SUCCESS) - || !TEST_mem_eq(MSG1, readbytes, buf, strlen(MSG1)) + || !TEST_size_t_eq(written, strlen(MSG1))) + goto end; + + if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, + sizeof(buf), &readbytes), + SSL_READ_EARLY_DATA_SUCCESS)) { + testresult = check_early_data_timeout(timer); + goto end; + } + + if (!TEST_mem_eq(MSG1, readbytes, buf, strlen(MSG1)) || !TEST_int_eq(SSL_get_early_data_status(serverssl), SSL_EARLY_DATA_ACCEPTED) || !TEST_true(create_ssl_connection(serverssl, clientssl, @@ -9038,7 +9318,7 @@ static int test_session_timeout(int test) * Test session ordering and timeout * Can't explicitly test performance of the new code, * but can test to see if the ordering of the sessions - * are correct, and they they are removed as expected + * are correct, and they are removed as expected */ SSL_SESSION *early = NULL; SSL_SESSION *middle = NULL; @@ -9156,30 +9436,150 @@ static int test_session_timeout(int test) } /* - * Test 0: Client sets servername and server acknowledges it (TLSv1.2) - * Test 1: Client sets servername and server does not acknowledge it (TLSv1.2) - * Test 2: Client sets inconsistent servername on resumption (TLSv1.2) - * Test 3: Client does not set servername on initial handshake (TLSv1.2) - * Test 4: Client does not set servername on resumption handshake (TLSv1.2) - * Test 5: Client sets servername and server acknowledges it (TLSv1.3) - * Test 6: Client sets servername and server does not acknowledge it (TLSv1.3) - * Test 7: Client sets inconsistent servername on resumption (TLSv1.3) - * Test 8: Client does not set servername on initial handshake(TLSv1.3) - * Test 9: Client does not set servername on resumption handshake (TLSv1.3) + * Test that a session cache overflow works as expected + * Test 0: TLSv1.3, timeout on new session later than old session + * Test 1: TLSv1.2, timeout on new session later than old session + * Test 2: TLSv1.3, timeout on new session earlier than old session + * Test 3: TLSv1.2, timeout on new session earlier than old session */ -static int test_servername(int tst) +#if !defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2) +static int test_session_cache_overflow(int idx) { - SSL_CTX *cctx = NULL, *sctx = NULL; - SSL *clientssl = NULL, *serverssl = NULL; + SSL_CTX *sctx = NULL, *cctx = NULL; + SSL *serverssl = NULL, *clientssl = NULL; int testresult = 0; SSL_SESSION *sess = NULL; - const char *sexpectedhost = NULL, *cexpectedhost = NULL; +#ifdef OSSL_NO_USABLE_TLS1_3 + /* If no TLSv1.3 available then do nothing in this case */ + if (idx % 2 == 0) + return TEST_skip("No TLSv1.3 available"); +#endif #ifdef OPENSSL_NO_TLS1_2 - if (tst <= 4) - return 1; + /* If no TLSv1.2 available then do nothing in this case */ + if (idx % 2 == 1) + return TEST_skip("No TLSv1.2 available"); #endif -#ifdef OSSL_NO_USABLE_TLS1_3 + + if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), + TLS_client_method(), TLS1_VERSION, + (idx % 2 == 0) ? TLS1_3_VERSION + : TLS1_2_VERSION, + &sctx, &cctx, cert, privkey)) + || !TEST_true(SSL_CTX_set_options(sctx, SSL_OP_NO_TICKET))) + goto end; + + SSL_CTX_sess_set_get_cb(sctx, get_session_cb); + get_sess_val = NULL; + + SSL_CTX_sess_set_cache_size(sctx, 1); + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL))) + goto end; + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) + goto end; + + if (idx > 1) { + sess = SSL_get_session(serverssl); + if (!TEST_ptr(sess)) + goto end; + + /* + * Cause this session to have a longer timeout than the next session to + * be added. + */ + if (!TEST_true(SSL_SESSION_set_timeout(sess, LONG_MAX))) { + sess = NULL; + goto end; + } + sess = NULL; + } + + SSL_shutdown(serverssl); + SSL_shutdown(clientssl); + SSL_free(serverssl); + SSL_free(clientssl); + serverssl = clientssl = NULL; + + /* + * Session cache size is 1 and we already populated the cache with a session + * so the next connection should cause an overflow. + */ + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL))) + goto end; + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) + goto end; + + /* + * The session we just negotiated may have been already removed from the + * internal cache - but we will return it anyway from our external cache. + */ + get_sess_val = SSL_get_session(serverssl); + if (!TEST_ptr(get_sess_val)) + goto end; + sess = SSL_get1_session(clientssl); + if (!TEST_ptr(sess)) + goto end; + + SSL_shutdown(serverssl); + SSL_shutdown(clientssl); + SSL_free(serverssl); + SSL_free(clientssl); + serverssl = clientssl = NULL; + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL))) + goto end; + + if (!TEST_true(SSL_set_session(clientssl, sess))) + goto end; + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) + goto end; + + testresult = 1; + + end: + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + SSL_SESSION_free(sess); + + return testresult; +} +#endif /* !defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2) */ + +/* + * Test 0: Client sets servername and server acknowledges it (TLSv1.2) + * Test 1: Client sets servername and server does not acknowledge it (TLSv1.2) + * Test 2: Client sets inconsistent servername on resumption (TLSv1.2) + * Test 3: Client does not set servername on initial handshake (TLSv1.2) + * Test 4: Client does not set servername on resumption handshake (TLSv1.2) + * Test 5: Client sets servername and server acknowledges it (TLSv1.3) + * Test 6: Client sets servername and server does not acknowledge it (TLSv1.3) + * Test 7: Client sets inconsistent servername on resumption (TLSv1.3) + * Test 8: Client does not set servername on initial handshake(TLSv1.3) + * Test 9: Client does not set servername on resumption handshake (TLSv1.3) + */ +static int test_servername(int tst) +{ + SSL_CTX *cctx = NULL, *sctx = NULL; + SSL *clientssl = NULL, *serverssl = NULL; + int testresult = 0; + SSL_SESSION *sess = NULL; + const char *sexpectedhost = NULL, *cexpectedhost = NULL; + +#ifdef OPENSSL_NO_TLS1_2 + if (tst <= 4) + return 1; +#endif +#ifdef OSSL_NO_USABLE_TLS1_3 if (tst >= 5) return 1; #endif @@ -9309,6 +9709,64 @@ static int test_servername(int tst) return testresult; } +static int test_unknown_sigalgs_groups(void) +{ + int ret = 0; + SSL_CTX *ctx = NULL; + + if (!TEST_ptr(ctx = SSL_CTX_new_ex(libctx, NULL, TLS_server_method()))) + goto end; + + if (!TEST_int_gt(SSL_CTX_set1_sigalgs_list(ctx, + "RSA+SHA256:?nonexistent:?RSA+SHA512"), + 0)) + goto end; + if (!TEST_size_t_eq(ctx->cert->conf_sigalgslen, 2) + || !TEST_int_eq(ctx->cert->conf_sigalgs[0], TLSEXT_SIGALG_rsa_pkcs1_sha256) + || !TEST_int_eq(ctx->cert->conf_sigalgs[1], TLSEXT_SIGALG_rsa_pkcs1_sha512)) + goto end; + + if (!TEST_int_gt(SSL_CTX_set1_client_sigalgs_list(ctx, + "RSA+SHA256:?nonexistent:?RSA+SHA512"), + 0)) + goto end; + if (!TEST_size_t_eq(ctx->cert->client_sigalgslen, 2) + || !TEST_int_eq(ctx->cert->client_sigalgs[0], TLSEXT_SIGALG_rsa_pkcs1_sha256) + || !TEST_int_eq(ctx->cert->client_sigalgs[1], TLSEXT_SIGALG_rsa_pkcs1_sha512)) + goto end; + + if (!TEST_int_le(SSL_CTX_set1_groups_list(ctx, + "nonexistent"), + 0)) + goto end; + + if (!TEST_int_le(SSL_CTX_set1_groups_list(ctx, + "?nonexistent1:?nonexistent2:?nonexistent3"), + 0)) + goto end; + +#ifndef OPENSSL_NO_EC + if (!TEST_int_le(SSL_CTX_set1_groups_list(ctx, + "P-256:nonexistent"), + 0)) + goto end; + + if (!TEST_int_gt(SSL_CTX_set1_groups_list(ctx, + "P-384:?nonexistent:?P-521"), + 0)) + goto end; + if (!TEST_size_t_eq(ctx->ext.supportedgroups_len, 2) + || !TEST_int_eq(ctx->ext.supportedgroups[0], OSSL_TLS_GROUP_ID_secp384r1) + || !TEST_int_eq(ctx->ext.supportedgroups[1], OSSL_TLS_GROUP_ID_secp521r1)) + goto end; +#endif + + ret = 1; + end: + SSL_CTX_free(ctx); + return ret; +} + #if !defined(OPENSSL_NO_EC) \ && (!defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2)) /* @@ -9475,20 +9933,11 @@ static int test_pluggable_group(int idx) OSSL_PROVIDER *tlsprov = OSSL_PROVIDER_load(libctx, "tls-provider"); /* Check that we are not impacted by a provider without any groups */ OSSL_PROVIDER *legacyprov = OSSL_PROVIDER_load(libctx, "legacy"); - const char *group_name = idx == 0 ? "xorgroup" : "xorkemgroup"; + const char *group_name = idx == 0 ? "xorkemgroup" : "xorgroup"; if (!TEST_ptr(tlsprov)) goto end; - if (legacyprov == NULL) { - /* - * In this case we assume we've been built with "no-legacy" and skip - * this test (there is no OPENSSL_NO_LEGACY) - */ - testresult = 1; - goto end; - } - if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), TLS_client_method(), TLS1_3_VERSION, @@ -9498,7 +9947,9 @@ static int test_pluggable_group(int idx) NULL, NULL))) goto end; - if (!TEST_true(SSL_set1_groups_list(serverssl, group_name)) + /* ensure GROUPLIST_INCREMENT (=40) logic triggers: */ + if (!TEST_true(SSL_set1_groups_list(serverssl, "xorgroup:xorkemgroup:dummy1:dummy2:dummy3:dummy4:dummy5:dummy6:dummy7:dummy8:dummy9:dummy10:dummy11:dummy12:dummy13:dummy14:dummy15:dummy16:dummy17:dummy18:dummy19:dummy20:dummy21:dummy22:dummy23:dummy24:dummy25:dummy26:dummy27:dummy28:dummy29:dummy30:dummy31:dummy32:dummy33:dummy34:dummy35:dummy36:dummy37:dummy38:dummy39:dummy40:dummy41:dummy42:dummy43")) + /* removing a single algorithm from the list makes the test pass */ || !TEST_true(SSL_set1_groups_list(clientssl, group_name))) goto end; @@ -9533,7 +9984,7 @@ static int test_pluggable_group(int idx) */ static int create_cert_key(int idx, char *certfilename, char *privkeyfilename) { - EVP_PKEY_CTX * evpctx = EVP_PKEY_CTX_new_from_name(libctx, + EVP_PKEY_CTX *evpctx = EVP_PKEY_CTX_new_from_name(libctx, (idx == 0) ? "xorhmacsig" : "xorhmacsha2sig", NULL); EVP_PKEY *pkey = NULL; X509 *x509 = X509_new(); @@ -9714,6 +10165,94 @@ static int test_ssl_dup(void) return testresult; } +static int secret_cb(SSL *s, void *secretin, int *secret_len, + STACK_OF(SSL_CIPHER) *peer_ciphers, + const SSL_CIPHER **cipher, void *arg) +{ + int i; + unsigned char *secret = secretin; + + /* Just use a fixed master secret */ + for (i = 0; i < *secret_len; i++) + secret[i] = 0xff; + + /* We don't set a preferred cipher */ + + return 1; +} + +/* + * Test the session_secret_cb which is designed for use with EAP-FAST + */ +static int test_session_secret_cb(void) +{ + SSL_CTX *cctx = NULL, *sctx = NULL; + SSL *clientssl = NULL, *serverssl = NULL; + SSL_SESSION *secret_sess = NULL; + int testresult = 0; + + if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), + TLS_client_method(), + 0, + 0, + &sctx, &cctx, cert, privkey))) + goto end; + + /* Create an initial connection and save the session */ + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL))) + goto end; + + /* session_secret_cb does not support TLSv1.3 */ + if (!TEST_true(SSL_set_min_proto_version(clientssl, TLS1_2_VERSION)) + || !TEST_true(SSL_set_max_proto_version(serverssl, TLS1_2_VERSION))) + goto end; + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) + goto end; + + if (!TEST_ptr(secret_sess = SSL_get1_session(clientssl))) + goto end; + + shutdown_ssl_connection(serverssl, clientssl); + serverssl = clientssl = NULL; + + /* Resume the earlier session */ + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL))) + goto end; + + /* + * No session ids for EAP-FAST - otherwise the state machine gets very + * confused. + */ + if (!TEST_true(SSL_SESSION_set1_id(secret_sess, NULL, 0))) + goto end; + + if (!TEST_true(SSL_set_min_proto_version(clientssl, TLS1_2_VERSION)) + || !TEST_true(SSL_set_max_proto_version(serverssl, TLS1_2_VERSION)) + || !TEST_true(SSL_set_session_secret_cb(serverssl, secret_cb, + NULL)) + || !TEST_true(SSL_set_session_secret_cb(clientssl, secret_cb, + NULL)) + || !TEST_true(SSL_set_session(clientssl, secret_sess))) + goto end; + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) + goto end; + + testresult = 1; + + end: + SSL_SESSION_free(secret_sess); + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + + return testresult; +} + # ifndef OPENSSL_NO_DH static EVP_PKEY *tmp_dh_params = NULL; @@ -10654,6 +11193,27 @@ end: #endif /* OSSL_NO_USABLE_TLS1_3 */ #if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_DYNAMIC_ENGINE) + +static ENGINE *load_dasync(void) +{ + ENGINE *e; + + if (!TEST_ptr(e = ENGINE_by_id("dasync"))) + return NULL; + + if (!TEST_true(ENGINE_init(e))) { + ENGINE_free(e); + return NULL; + } + + if (!TEST_true(ENGINE_register_ciphers(e))) { + ENGINE_free(e); + return NULL; + } + + return e; +} + /* * Test TLSv1.2 with a pipeline capable cipher. TLSv1.3 and DTLS do not * support this yet. The only pipeline capable cipher that we have is in the @@ -10669,6 +11229,8 @@ end: * Test 4: Client has pipelining enabled, server does not: more data than all * the available pipelines can take * Test 5: Client has pipelining enabled, server does not: Maximum size pipeline + * Test 6: Repeat of test 0, but the engine is loaded late (after the SSL_CTX + * is created) */ static int test_pipelining(int idx) { @@ -10681,25 +11243,28 @@ static int test_pipelining(int idx) size_t written, readbytes, offset, msglen, fragsize = 10, numpipes = 5; size_t expectedreads; unsigned char *buf = NULL; - ENGINE *e; - - if (!TEST_ptr(e = ENGINE_by_id("dasync"))) - return 0; + ENGINE *e = NULL; - if (!TEST_true(ENGINE_init(e))) { - ENGINE_free(e); - return 0; + if (idx != 6) { + e = load_dasync(); + if (e == NULL) + return 0; } - if (!TEST_true(ENGINE_register_ciphers(e))) - goto end; - if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), TLS_client_method(), 0, TLS1_2_VERSION, &sctx, &cctx, cert, privkey))) goto end; + if (idx == 6) { + e = load_dasync(); + if (e == NULL) + goto end; + /* Now act like test 0 */ + idx = 0; + } + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL))) goto end; @@ -10835,11 +11400,13 @@ end: SSL_free(clientssl); SSL_CTX_free(sctx); SSL_CTX_free(cctx); - ENGINE_unregister_ciphers(e); - ENGINE_finish(e); - ENGINE_free(e); + if (e != NULL) { + ENGINE_unregister_ciphers(e); + ENGINE_finish(e); + ENGINE_free(e); + } OPENSSL_free(buf); - if (idx == 5) + if (fragsize == SSL3_RT_MAX_PLAIN_LENGTH) OPENSSL_free(msg); return testresult; } @@ -11064,6 +11631,369 @@ end: return testresult; } +/* + * Force a write retry during handshaking. We test various combinations of + * scenarios. We test a large certificate message which will fill the buffering + * BIO used in the handshake. We try with client auth on and off. Finally we + * also try a BIO that indicates retry via a 0 return. BIO_write() is documented + * to indicate retry via -1 - but sometimes BIOs don't do that. + * + * Test 0: Standard certificate message + * Test 1: Large certificate message + * Test 2: Standard cert, verify peer + * Test 3: Large cert, verify peer + * Test 4: Standard cert, BIO returns 0 on retry + * Test 5: Large cert, BIO returns 0 on retry + * Test 6: Standard cert, verify peer, BIO returns 0 on retry + * Test 7: Large cert, verify peer, BIO returns 0 on retry + * Test 8-15: Repeat of above with TLSv1.2 + */ +static int test_handshake_retry(int idx) +{ + SSL_CTX *cctx = NULL, *sctx = NULL; + SSL *clientssl = NULL, *serverssl = NULL; + int testresult = 0; + BIO *tmp = NULL, *bretry = BIO_new(bio_s_always_retry()); + int maxversion = 0; + + if (!TEST_ptr(bretry)) + goto end; + +#ifndef OPENSSL_NO_TLS1_2 + if ((idx & 8) == 8) + maxversion = TLS1_2_VERSION; +#else + if ((idx & 8) == 8) + return TEST_skip("No TLSv1.2"); +#endif + + if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), + TLS_client_method(), 0, maxversion, + &sctx, &cctx, cert, privkey))) + goto end; + + /* + * Add a large amount of data to fill the buffering BIO used by the SSL + * object + */ + if ((idx & 1) == 1 && !ssl_ctx_add_large_cert_chain(libctx, sctx, cert)) + goto end; + + /* + * We don't actually configure a client cert, but neither do we fail if one + * isn't present. + */ + if ((idx & 2) == 2) + SSL_CTX_set_verify(sctx, SSL_VERIFY_PEER, NULL); + + if ((idx & 4) == 4) + set_always_retry_err_val(0); + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, + &clientssl, NULL, NULL))) + goto end; + + tmp = SSL_get_wbio(serverssl); + if (!TEST_ptr(tmp) || !TEST_true(BIO_up_ref(tmp))) { + tmp = NULL; + goto end; + } + SSL_set0_wbio(serverssl, bretry); + bretry = NULL; + + if (!TEST_int_eq(SSL_connect(clientssl), -1)) + goto end; + + if (!TEST_int_eq(SSL_accept(serverssl), -1) + || !TEST_int_eq(SSL_get_error(serverssl, -1), SSL_ERROR_WANT_WRITE)) + goto end; + + /* Restore a BIO that will let the write succeed */ + SSL_set0_wbio(serverssl, tmp); + tmp = NULL; + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) + goto end; + + testresult = 1; +end: + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + BIO_free(bretry); + BIO_free(tmp); + set_always_retry_err_val(-1); + return testresult; +} + +/* + * Test that receiving retries when writing application data works as expected + */ +static int test_data_retry(void) +{ + SSL_CTX *cctx = NULL, *sctx = NULL; + SSL *clientssl = NULL, *serverssl = NULL; + int testresult = 0; + unsigned char inbuf[1200], outbuf[1200]; + size_t i; + BIO *tmp = NULL; + BIO *bretry = BIO_new(bio_s_maybe_retry()); + size_t written, readbytes, totread = 0; + + if (!TEST_ptr(bretry)) + goto end; + + for (i = 0; i < sizeof(inbuf); i++) + inbuf[i] = (unsigned char)(0xff & i); + memset(outbuf, 0, sizeof(outbuf)); + + if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), + TLS_client_method(), 0, 0, &sctx, &cctx, + cert, privkey))) + goto end; + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, + NULL))) + goto end; + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) + goto end; + + /* Smallest possible max send fragment is 512 */ + if (!TEST_true(SSL_set_max_send_fragment(clientssl, 512))) + goto end; + + tmp = SSL_get_wbio(clientssl); + if (!TEST_ptr(tmp)) + goto end; + if (!TEST_true(BIO_up_ref(tmp))) + goto end; + BIO_push(bretry, tmp); + tmp = NULL; + SSL_set0_wbio(clientssl, bretry); + if (!BIO_up_ref(bretry)) { + bretry = NULL; + goto end; + } + + for (i = 0; i < 3; i++) { + /* We expect this call to make no progress and indicate retry */ + if (!TEST_false(SSL_write_ex(clientssl, inbuf, sizeof(inbuf), &written))) + goto end; + if (!TEST_int_eq(SSL_get_error(clientssl, 0), SSL_ERROR_WANT_WRITE)) + goto end; + + /* Allow one write to progress, but the next one to signal retry */ + if (!TEST_true(BIO_ctrl(bretry, MAYBE_RETRY_CTRL_SET_RETRY_AFTER_CNT, 1, + NULL))) + goto end; + + if (i == 2) + break; + + /* + * This call will hopefully make progress but will still indicate retry + * because there is more data than will fit into a single record. + */ + if (!TEST_false(SSL_write_ex(clientssl, inbuf, sizeof(inbuf), &written))) + goto end; + if (!TEST_int_eq(SSL_get_error(clientssl, 0), SSL_ERROR_WANT_WRITE)) + goto end; + } + + /* The final call should write the last chunk of data and succeed */ + if (!TEST_true(SSL_write_ex(clientssl, inbuf, sizeof(inbuf), &written))) + goto end; + /* Read all the data available */ + while (SSL_read_ex(serverssl, outbuf + totread, sizeof(outbuf) - totread, + &readbytes)) + totread += readbytes; + if (!TEST_mem_eq(inbuf, sizeof(inbuf), outbuf, totread)) + goto end; + + testresult = 1; +end: + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + BIO_free_all(bretry); + BIO_free(tmp); + return testresult; +} + +struct resume_servername_cb_data { + int i; + SSL_CTX *cctx; + SSL_CTX *sctx; + SSL_SESSION *sess; + int recurse; +}; + +/* + * Servername callback. We use it here to run another complete handshake using + * the same session - and mark the session as not_resuamble at the end + */ +static int resume_servername_cb(SSL *s, int *ad, void *arg) +{ + struct resume_servername_cb_data *cbdata = arg; + SSL *serverssl = NULL, *clientssl = NULL; + int ret = SSL_TLSEXT_ERR_ALERT_FATAL; + + if (cbdata->recurse) + return SSL_TLSEXT_ERR_ALERT_FATAL; + + if ((cbdata->i % 3) != 1) + return SSL_TLSEXT_ERR_OK; + + cbdata->recurse = 1; + + if (!TEST_true(create_ssl_objects(cbdata->sctx, cbdata->cctx, &serverssl, + &clientssl, NULL, NULL)) + || !TEST_true(SSL_set_session(clientssl, cbdata->sess))) + goto end; + + ERR_set_mark(); + /* + * We expect this to fail - because the servername cb will fail. This will + * mark the session as not_resumable. + */ + if (!TEST_false(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) { + ERR_clear_last_mark(); + goto end; + } + ERR_pop_to_mark(); + + ret = SSL_TLSEXT_ERR_OK; + end: + SSL_free(serverssl); + SSL_free(clientssl); + cbdata->recurse = 0; + return ret; +} +/* + * Test multiple resumptions and cache size handling + * Test 0: TLSv1.3 (max_early_data set) + * Test 1: TLSv1.3 (SSL_OP_NO_TICKET set) + * Test 2: TLSv1.3 (max_early_data and SSL_OP_NO_TICKET set) + * Test 3: TLSv1.3 (SSL_OP_NO_TICKET, simultaneous resumes) + * Test 4: TLSv1.2 + */ +static int test_multi_resume(int idx) +{ + SSL_CTX *sctx = NULL, *cctx = NULL; + SSL *serverssl = NULL, *clientssl = NULL; + SSL_SESSION *sess = NULL; + int max_version = TLS1_3_VERSION; + int i, testresult = 0; + struct resume_servername_cb_data cbdata; + +#if defined(OPENSSL_NO_TLS1_2) + if (idx == 4) + return TEST_skip("TLSv1.2 is disabled in this build"); +#else + if (idx == 4) + max_version = TLS1_2_VERSION; +#endif +#if defined(OSSL_NO_USABLE_TLS1_3) + if (idx != 4) + return TEST_skip("No usable TLSv1.3 in this build"); +#endif + + if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), + TLS_client_method(), TLS1_VERSION, + max_version, &sctx, &cctx, cert, + privkey))) + goto end; + + /* + * TLSv1.3 only uses a session cache if either max_early_data > 0 (used for + * replay protection), or if SSL_OP_NO_TICKET is in use + */ + if (idx == 0 || idx == 2) { + if (!TEST_true(SSL_CTX_set_max_early_data(sctx, 1024))) + goto end; + } + if (idx == 1 || idx == 2 || idx == 3) + SSL_CTX_set_options(sctx, SSL_OP_NO_TICKET); + + SSL_CTX_sess_set_cache_size(sctx, 5); + + if (idx == 3) { + SSL_CTX_set_tlsext_servername_callback(sctx, resume_servername_cb); + SSL_CTX_set_tlsext_servername_arg(sctx, &cbdata); + cbdata.cctx = cctx; + cbdata.sctx = sctx; + cbdata.recurse = 0; + } + + for (i = 0; i < 30; i++) { + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL)) + || !TEST_true(SSL_set_session(clientssl, sess))) + goto end; + + /* + * Check simultaneous resumes. We pause the connection part way through + * the handshake by (mis)using the servername_cb. The pause occurs after + * session resumption has already occurred, but before any session + * tickets have been issued. While paused we run another complete + * handshake resuming the same session. + */ + if (idx == 3) { + cbdata.i = i; + cbdata.sess = sess; + } + + /* + * Recreate a bug where dynamically changing the max_early_data value + * can cause sessions in the session cache which cannot be deleted. + */ + if ((idx == 0 || idx == 2) && (i % 3) == 2) + SSL_set_max_early_data(serverssl, 0); + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) + goto end; + + if (sess == NULL || (idx == 0 && (i % 3) == 2)) { + if (!TEST_false(SSL_session_reused(clientssl))) + goto end; + } else { + if (!TEST_true(SSL_session_reused(clientssl))) + goto end; + } + SSL_SESSION_free(sess); + + /* Do a full handshake, followed by two resumptions */ + if ((i % 3) == 2) { + sess = NULL; + } else { + if (!TEST_ptr((sess = SSL_get1_session(clientssl)))) + goto end; + } + + SSL_shutdown(clientssl); + SSL_shutdown(serverssl); + SSL_free(serverssl); + SSL_free(clientssl); + serverssl = clientssl = NULL; + } + + /* We should never exceed the session cache size limit */ + if (!TEST_long_le(SSL_CTX_sess_number(sctx), 5)) + goto end; + + testresult = 1; + end: + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + SSL_SESSION_free(sess); + return testresult; +} + OPT_TEST_DECLARE_USAGE("certfile privkeyfile srpvfile tmpfile provider config dhfile\n") int setup_tests(void) @@ -11266,7 +12196,7 @@ int setup_tests(void) ADD_ALL_TESTS(test_early_data_skip_abort, OSSL_NELEM(ciphersuites) * 3); ADD_ALL_TESTS(test_early_data_not_sent, 3); ADD_ALL_TESTS(test_early_data_psk, 8); - ADD_ALL_TESTS(test_early_data_psk_with_all_ciphers, 5); + ADD_ALL_TESTS(test_early_data_psk_with_all_ciphers, 7); ADD_ALL_TESTS(test_early_data_not_expected, 3); # ifndef OPENSSL_NO_TLS1_2 ADD_ALL_TESTS(test_early_data_tls1_2, 3); @@ -11281,6 +12211,9 @@ int setup_tests(void) # else ADD_ALL_TESTS(test_tls13_psk, 4); # endif /* OPENSSL_NO_PSK */ +#ifndef OSSL_NO_USABLE_TLS1_3 + ADD_ALL_TESTS(test_tls13_no_dhe_kex, 8); +#endif /* OSSL_NO_USABLE_TLS1_3 */ # ifndef OPENSSL_NO_TLS1_2 /* Test with both TLSv1.3 and 1.2 versions */ ADD_ALL_TESTS(test_key_exchange, 14); @@ -11308,7 +12241,7 @@ int setup_tests(void) ADD_ALL_TESTS(test_key_update_local_in_write, 2); ADD_ALL_TESTS(test_key_update_local_in_read, 2); #endif - ADD_ALL_TESTS(test_ssl_clear, 2); + ADD_ALL_TESTS(test_ssl_clear, 8); ADD_ALL_TESTS(test_max_fragment_len_ext, OSSL_NELEM(max_fragment_len_test)); #if !defined(OPENSSL_NO_SRP) && !defined(OPENSSL_NO_TLS1_2) ADD_ALL_TESTS(test_srp, 6); @@ -11332,6 +12265,7 @@ int setup_tests(void) ADD_ALL_TESTS(test_multiblock_write, OSSL_NELEM(multiblock_cipherlist_data)); #endif ADD_ALL_TESTS(test_servername, 10); + ADD_TEST(test_unknown_sigalgs_groups); #if !defined(OPENSSL_NO_EC) \ && (!defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2)) ADD_ALL_TESTS(test_sigalgs_available, 6); @@ -11342,6 +12276,7 @@ int setup_tests(void) #endif #ifndef OPENSSL_NO_TLS1_2 ADD_TEST(test_ssl_dup); + ADD_TEST(test_session_secret_cb); # ifndef OPENSSL_NO_DH ADD_ALL_TESTS(test_set_tmp_dh, 11); ADD_ALL_TESTS(test_dh_auto, 7); @@ -11356,6 +12291,9 @@ int setup_tests(void) ADD_TEST(test_set_verify_cert_store_ssl_ctx); ADD_TEST(test_set_verify_cert_store_ssl); ADD_ALL_TESTS(test_session_timeout, 1); +#if !defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2) + ADD_ALL_TESTS(test_session_cache_overflow, 4); +#endif ADD_TEST(test_load_dhfile); #ifndef OSSL_NO_USABLE_TLS1_3 ADD_TEST(test_read_ahead_key_change); @@ -11365,10 +12303,13 @@ int setup_tests(void) ADD_ALL_TESTS(test_serverinfo_custom, 4); #endif #if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_DYNAMIC_ENGINE) - ADD_ALL_TESTS(test_pipelining, 6); + ADD_ALL_TESTS(test_pipelining, 7); #endif ADD_ALL_TESTS(test_version, 6); ADD_TEST(test_rstate_string); + ADD_ALL_TESTS(test_handshake_retry, 16); + ADD_TEST(test_data_retry); + ADD_ALL_TESTS(test_multi_resume, 5); return 1; err: @@ -11398,6 +12339,7 @@ void cleanup_tests(void) OPENSSL_free(privkey8192); bio_s_mempacket_test_free(); bio_s_always_retry_free(); + bio_s_maybe_retry_free(); OSSL_PROVIDER_unload(defctxnull); OSSL_LIB_CTX_free(libctx); }