Skip to content

Commit

Permalink
Extend the multi_resume test for simultaneous resumptions
Browse files Browse the repository at this point in the history
Test what happens if the same session gets resumed multiple times at the
same time - and one of them gets marked as not_resumable.

Related to CVE-2024-2511

Reviewed-by: Neil Horman <nhorman@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from openssl/openssl#24044)

(cherry picked from commit 031b11a4054c972a5e2f07dfa81ce1842453253e)
Signed-off-by: Liu-Ermeng <liuermeng2@huawei.com>
Signed-off-by: hhhFun <fanghaojie@huawei.com>
  • Loading branch information
mattcaswell authored and hhhFun committed Apr 13, 2024
1 parent 1ec3704 commit fa8fa67
Showing 1 changed file with 85 additions and 4 deletions.
89 changes: 85 additions & 4 deletions test/sslapitest.c
Original file line number Diff line number Diff line change
Expand Up @@ -6848,12 +6848,63 @@ static int test_inherit_verify_param(void)
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.2
* Test 3: TLSv1.3 (SSL_OP_NO_TICKET, simultaneous resumes)
* Test 4: TLSv1.2
*/
static int test_multi_resume(int idx)
{
Expand All @@ -6862,9 +6913,19 @@ static int test_multi_resume(int idx)
SSL_SESSION *sess = NULL;
int max_version = TLS1_3_VERSION;
int i, testresult = 0;
struct resume_servername_cb_data cbdata;

if (idx == 3)
#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(TLS_server_method(),
TLS_client_method(), TLS1_VERSION,
Expand All @@ -6880,17 +6941,37 @@ static int test_multi_resume(int idx)
if (!TEST_true(SSL_CTX_set_max_early_data(sctx, 1024)))
goto end;
}
if (idx == 1 || idx == 2)
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.
Expand Down Expand Up @@ -7067,7 +7148,7 @@ int setup_tests(void)
#endif
ADD_TEST(test_set_alpn);
ADD_TEST(test_inherit_verify_param);
ADD_ALL_TESTS(test_multi_resume, 4);
ADD_ALL_TESTS(test_multi_resume, 5);
return 1;
}

Expand Down

0 comments on commit fa8fa67

Please sign in to comment.