From 85e247ebc08c07ed4a86f8a128ddceeb3f48bcbc Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Mon, 27 Feb 2023 18:38:03 +0000 Subject: [PATCH] Test that there are no errors on the stack for rejected early data If we reject early data then it is normal for decryption operations to fail. We should ensure there are no spurious errors on the stack in that case. This adds a test for that scenario. Reviewed-by: Tomas Mraz Reviewed-by: Dmitry Belyavskiy (Merged from https://github.com/openssl/openssl/pull/20442) --- test/sslapitest.c | 123 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 94 insertions(+), 29 deletions(-) diff --git a/test/sslapitest.c b/test/sslapitest.c index 77d260aa0cd27..ef7eb5b660a02 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -77,7 +77,7 @@ 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); +static SSL_SESSION *create_a_psk(SSL *ssl, size_t mdsize); #endif static char *certsdir = NULL; @@ -2652,7 +2652,7 @@ static int test_psk_tickets(void) if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL))) goto end; - clientpsk = serverpsk = create_a_psk(clientssl); + clientpsk = serverpsk = create_a_psk(clientssl, SHA384_DIGEST_LENGTH); if (!TEST_ptr(clientpsk)) goto end; SSL_SESSION_up_ref(clientpsk); @@ -3346,7 +3346,7 @@ static unsigned int psk_server_cb(SSL *ssl, const char *identity, #define TLS13_AES_128_CCM_8_SHA256_BYTES ((const unsigned char *)"\x13\05") -static SSL_SESSION *create_a_psk(SSL *ssl) +static SSL_SESSION *create_a_psk(SSL *ssl, size_t mdsize) { const SSL_CIPHER *cipher = NULL; const unsigned char key[] = { @@ -3354,16 +3354,26 @@ static SSL_SESSION *create_a_psk(SSL *ssl) 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, - 0x2c, 0x2d, 0x2e, 0x2f + 0x2c, 0x2d, 0x2e, 0x2f /* SHA384_DIGEST_LENGTH bytes */ }; SSL_SESSION *sess = NULL; - cipher = SSL_CIPHER_find(ssl, TLS13_AES_256_GCM_SHA384_BYTES); + if (mdsize == SHA384_DIGEST_LENGTH) { + cipher = SSL_CIPHER_find(ssl, TLS13_AES_256_GCM_SHA384_BYTES); + } else if (mdsize == SHA256_DIGEST_LENGTH) { + /* + * Any ciphersuite using SHA256 will do - it will be compatible with + * the actual ciphersuite selected as long as it too is based on SHA256 + */ + cipher = SSL_CIPHER_find(ssl, TLS13_AES_128_GCM_SHA256_BYTES); + } else { + /* Should not happen */ + return NULL; + } sess = SSL_SESSION_new(); if (!TEST_ptr(sess) || !TEST_ptr(cipher) - || !TEST_true(SSL_SESSION_set1_master_key(sess, key, - sizeof(key))) + || !TEST_true(SSL_SESSION_set1_master_key(sess, key, mdsize)) || !TEST_true(SSL_SESSION_set_cipher(sess, cipher)) || !TEST_true( SSL_SESSION_set_protocol_version(sess, @@ -3379,7 +3389,8 @@ static SSL_SESSION *create_a_psk(SSL *ssl) * error. */ static int setupearly_data_test(SSL_CTX **cctx, SSL_CTX **sctx, SSL **clientssl, - SSL **serverssl, SSL_SESSION **sess, int idx) + SSL **serverssl, SSL_SESSION **sess, int idx, + size_t mdsize) { if (*sctx == NULL && !TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), @@ -3419,7 +3430,7 @@ static int setupearly_data_test(SSL_CTX **cctx, SSL_CTX **sctx, SSL **clientssl, return 0; if (idx == 2) { - clientpsk = create_a_psk(*clientssl); + clientpsk = create_a_psk(*clientssl, mdsize); if (!TEST_ptr(clientpsk) /* * We just choose an arbitrary value for max_early_data which @@ -3479,7 +3490,8 @@ static int test_early_data_read_write(int idx) BIO *rbio; if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl, - &serverssl, &sess, idx))) + &serverssl, &sess, idx, + SHA384_DIGEST_LENGTH))) goto end; /* Write and read some early data */ @@ -3736,7 +3748,8 @@ static int test_early_data_replay_int(int idx, int usecb, int confopt) } if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl, - &serverssl, &sess, idx))) + &serverssl, &sess, idx, + SHA384_DIGEST_LENGTH))) goto end; /* @@ -3826,6 +3839,16 @@ static int test_early_data_replay(int idx) return ret; } +static const char *ciphersuites[] = { + "TLS_AES_128_CCM_8_SHA256", + "TLS_AES_128_GCM_SHA256", + "TLS_AES_256_GCM_SHA384", + "TLS_AES_128_CCM_SHA256", +#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305) + "TLS_CHACHA20_POLY1305_SHA256" +#endif +}; + /* * Helper function to test that a server attempting to read early data can * handle a connection from a client where the early data should be skipped. @@ -3834,7 +3857,7 @@ static int test_early_data_replay(int idx) * testtype: 2 == HRR, invalid early_data sent after HRR * testtype: 3 == recv_max_early_data set to 0 */ -static int early_data_skip_helper(int testtype, int idx) +static int early_data_skip_helper(int testtype, int cipher, int idx) { SSL_CTX *cctx = NULL, *sctx = NULL; SSL *clientssl = NULL, *serverssl = NULL; @@ -3843,8 +3866,28 @@ static int early_data_skip_helper(int testtype, int idx) unsigned char buf[20]; size_t readbytes, written; + if (is_fips && cipher == 4) + return 1; + + 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) { + SSL_CTX_set_security_level(sctx, 0); + SSL_CTX_set_security_level(cctx, 0); + } + + if (!TEST_true(SSL_CTX_set_ciphersuites(sctx, ciphersuites[cipher])) + || !TEST_true(SSL_CTX_set_ciphersuites(cctx, ciphersuites[cipher]))) + goto end; + if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl, - &serverssl, &sess, idx))) + &serverssl, &sess, idx, + cipher == 2 ? SHA384_DIGEST_LENGTH + : SHA256_DIGEST_LENGTH))) goto end; if (testtype == 1 || testtype == 2) { @@ -3954,6 +3997,7 @@ static int early_data_skip_helper(int testtype, int idx) goto end; } + ERR_clear_error(); /* * Should be able to send normal data despite rejection of early data. The * early_data should be skipped. @@ -3966,6 +4010,13 @@ static int early_data_skip_helper(int testtype, int idx) || !TEST_mem_eq(buf, readbytes, MSG2, strlen(MSG2))) goto end; + /* + * Failure to decrypt early data records should not leave spurious errors + * on the error stack + */ + if (!TEST_long_eq(ERR_peek_error(), 0)) + goto end; + testresult = 1; end: @@ -3986,7 +4037,9 @@ static int early_data_skip_helper(int testtype, int idx) */ static int test_early_data_skip(int idx) { - return early_data_skip_helper(0, idx); + return early_data_skip_helper(0, + idx % OSSL_NELEM(ciphersuites), + idx / OSSL_NELEM(ciphersuites)); } /* @@ -3995,7 +4048,9 @@ static int test_early_data_skip(int idx) */ static int test_early_data_skip_hrr(int idx) { - return early_data_skip_helper(1, idx); + return early_data_skip_helper(1, + idx % OSSL_NELEM(ciphersuites), + idx / OSSL_NELEM(ciphersuites)); } /* @@ -4005,7 +4060,9 @@ static int test_early_data_skip_hrr(int idx) */ static int test_early_data_skip_hrr_fail(int idx) { - return early_data_skip_helper(2, idx); + return early_data_skip_helper(2, + idx % OSSL_NELEM(ciphersuites), + idx / OSSL_NELEM(ciphersuites)); } /* @@ -4014,7 +4071,9 @@ static int test_early_data_skip_hrr_fail(int idx) */ static int test_early_data_skip_abort(int idx) { - return early_data_skip_helper(3, idx); + return early_data_skip_helper(3, + idx % OSSL_NELEM(ciphersuites), + idx / OSSL_NELEM(ciphersuites)); } /* @@ -4031,7 +4090,8 @@ static int test_early_data_not_sent(int idx) size_t readbytes, written; if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl, - &serverssl, &sess, idx))) + &serverssl, &sess, idx, + SHA384_DIGEST_LENGTH))) goto end; /* Write some data - should block due to handshake with server */ @@ -4125,7 +4185,8 @@ static int test_early_data_psk(int idx) /* We always set this up with a final parameter of "2" for PSK */ if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl, - &serverssl, &sess, 2))) + &serverssl, &sess, 2, + SHA384_DIGEST_LENGTH))) goto end; servalpn = "goodalpn"; @@ -4324,7 +4385,8 @@ static int test_early_data_psk_with_all_ciphers(int idx) /* We always set this up with a final parameter of "2" for PSK */ if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl, - &serverssl, &sess, 2))) + &serverssl, &sess, 2, + SHA384_DIGEST_LENGTH))) goto end; if (!TEST_true(SSL_set_ciphersuites(clientssl, cipher_str[idx])) @@ -4397,7 +4459,8 @@ static int test_early_data_not_expected(int idx) size_t readbytes, written; if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl, - &serverssl, &sess, idx))) + &serverssl, &sess, idx, + SHA384_DIGEST_LENGTH))) goto end; /* Write some early data */ @@ -4456,7 +4519,8 @@ static int test_early_data_tls1_2(int idx) size_t readbytes, written; if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl, - &serverssl, NULL, idx))) + &serverssl, NULL, idx, + SHA384_DIGEST_LENGTH))) goto end; /* Write some data - should block due to handshake with server */ @@ -6310,7 +6374,7 @@ static int test_export_key_mat_early(int idx) size_t readbytes, written; if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl, &serverssl, - &sess, idx))) + &sess, idx, SHA384_DIGEST_LENGTH))) goto end; /* Here writing 0 length early data is enough. */ @@ -7395,7 +7459,8 @@ static int test_info_callback(int tst) /* early_data tests */ if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl, - &serverssl, &sess, 0))) + &serverssl, &sess, 0, + SHA384_DIGEST_LENGTH))) goto end; /* We don't actually need this reference */ @@ -10620,16 +10685,16 @@ int setup_tests(void) ADD_TEST(test_ccs_change_cipher); #endif #ifndef OSSL_NO_USABLE_TLS1_3 - ADD_ALL_TESTS(test_early_data_read_write, 3); + ADD_ALL_TESTS(test_early_data_read_write, 6); /* * We don't do replay tests for external PSK. Replay protection isn't used * in that scenario. */ ADD_ALL_TESTS(test_early_data_replay, 2); - ADD_ALL_TESTS(test_early_data_skip, 3); - ADD_ALL_TESTS(test_early_data_skip_hrr, 3); - ADD_ALL_TESTS(test_early_data_skip_hrr_fail, 3); - ADD_ALL_TESTS(test_early_data_skip_abort, 3); + ADD_ALL_TESTS(test_early_data_skip, OSSL_NELEM(ciphersuites) * 3); + ADD_ALL_TESTS(test_early_data_skip_hrr, OSSL_NELEM(ciphersuites) * 3); + ADD_ALL_TESTS(test_early_data_skip_hrr_fail, OSSL_NELEM(ciphersuites) * 3); + 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);