Skip to content

Commit

Permalink
Test that there are no errors on the stack for rejected early data
Browse files Browse the repository at this point in the history
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 <tomas@openssl.org>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
(Merged from #20442)
  • Loading branch information
mattcaswell authored and paulidale committed Mar 14, 2023
1 parent d015b50 commit 85e247e
Showing 1 changed file with 94 additions and 29 deletions.
123 changes: 94 additions & 29 deletions test/sslapitest.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -3346,24 +3346,34 @@ 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[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
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,
Expand All @@ -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(),
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;

/*
Expand Down Expand Up @@ -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.
Expand All @@ -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;
Expand All @@ -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) {
Expand Down Expand Up @@ -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.
Expand All @@ -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:
Expand All @@ -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));
}

/*
Expand All @@ -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));
}

/*
Expand All @@ -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));
}

/*
Expand All @@ -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));
}

/*
Expand All @@ -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 */
Expand Down Expand Up @@ -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";
Expand Down Expand Up @@ -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]))
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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. */
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 85e247e

Please sign in to comment.