Skip to content

Commit

Permalink
Extend the testing of resetting/clearing an SSL connection
Browse files Browse the repository at this point in the history
SSL_clear() explicitly clears an SSL object to enable it to be reused.
You can have a similar effect by calling SSL_set_accept_state() or
SSL_set_connect_state(). We extend the testing of SSL_clear() to use these
other methods. We also ensure we test the case where we have unread
bufferred data that needs to be cleared.

Reviewed-by: Hugo Landau <hlandau@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from #23256)
  • Loading branch information
mattcaswell committed Jan 31, 2024
1 parent f7f2b66 commit 5de8c49
Showing 1 changed file with 81 additions and 10 deletions.
91 changes: 81 additions & 10 deletions test/sslapitest.c
Original file line number Diff line number Diff line change
Expand Up @@ -7035,22 +7035,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,
Expand All @@ -7059,20 +7082,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);
Expand Down Expand Up @@ -11637,7 +11708,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);
Expand Down

0 comments on commit 5de8c49

Please sign in to comment.