From: Matt Caswell Date: Tue, 16 Jan 2024 13:53:30 +0000 (+0000) Subject: Extend the testing of resetting/clearing an SSL connection X-Git-Tag: openssl-3.3.0-alpha1~249 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5de8c49d6c019ad93149871989b755b5cc7b821c;p=thirdparty%2Fopenssl.git Extend the testing of resetting/clearing an SSL connection 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 Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/23256) --- diff --git a/test/sslapitest.c b/test/sslapitest.c index b8c474d524e..6ef64740db8 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -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, @@ -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); @@ -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);