From: Matt Caswell Date: Tue, 4 Jul 2023 15:28:41 +0000 (+0100) Subject: Add an SSL BIO test for QUIC X-Git-Tag: openssl-3.2.0-alpha1~480 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0a3733babbbb4e297ccfbc3ece29e95cafca5f2d;p=thirdparty%2Fopenssl.git Add an SSL BIO test for QUIC We create an SSL BIO using a QUIC based SSL_CTX and then use that BIO to create a connection and read/write data from streams. Reviewed-by: Paul Dale Reviewed-by: Hugo Landau Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/21367) --- diff --git a/test/helpers/quictestlib.c b/test/helpers/quictestlib.c index 52cf587c32a..1053a102de6 100644 --- a/test/helpers/quictestlib.c +++ b/test/helpers/quictestlib.c @@ -88,9 +88,12 @@ int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx, *qtserv = NULL; if (fault != NULL) *fault = NULL; - *cssl = SSL_new(clientctx); - if (!TEST_ptr(*cssl)) - return 0; + + if (*cssl == NULL) { + *cssl = SSL_new(clientctx); + if (!TEST_ptr(*cssl)) + return 0; + } /* SSL_set_alpn_protos returns 0 for success! */ if (!TEST_false(SSL_set_alpn_protos(*cssl, alpn, sizeof(alpn)))) diff --git a/test/quicapitest.c b/test/quicapitest.c index a6b7c88eba2..780224f07c6 100644 --- a/test/quicapitest.c +++ b/test/quicapitest.c @@ -608,6 +608,139 @@ err: return testresult; } +#define MAXLOOPS 1000 + +static int test_bio_ssl(void) +{ + /* + * We just use OSSL_QUIC_client_method() rather than + * OSSL_QUIC_client_thread_method(). We will never leave the connection idle + * so we will always be implicitly handling time events anyway via other + * IO calls. + */ + SSL_CTX *cctx = SSL_CTX_new_ex(libctx, NULL, OSSL_QUIC_client_method()); + SSL *clientquic = NULL, *stream = NULL; + QUIC_TSERVER *qtserv = NULL; + int testresult = 0; + BIO *cbio = NULL, *strbio = NULL, *thisbio; + const char *msg = "Hello world"; + int abortctr = 0, err, clienterr = 0, servererr = 0, retc = 0, rets = 0; + size_t written, readbytes, msglen; + int sid = 0, i; + unsigned char buf[80]; + + if (!TEST_ptr(cctx)) + goto err; + + cbio = BIO_new_ssl(cctx, 1); + if (!TEST_ptr(cbio)) + goto err; + + /* + * We must configure the ALPN/peer address etc so we get the SSL object in + * order to pass it to qtest_create_quic_objects for configuration. + */ + if (!TEST_int_eq(BIO_get_ssl(cbio, &clientquic), 1)) + goto err; + + if (!TEST_true(qtest_create_quic_objects(libctx, NULL, cert, privkey, + 0, &qtserv, &clientquic, NULL))) + goto err; + + msglen = strlen(msg); + + do { + err = BIO_FLAGS_WRITE; + while (!clienterr && !retc && err == BIO_FLAGS_WRITE) { + retc = BIO_write_ex(cbio, msg, msglen, &written); + if (!retc) { + if (BIO_should_retry(cbio)) + err = BIO_retry_type(cbio); + else + err = 0; + } + } + + if (!clienterr && retc <= 0 && err != BIO_FLAGS_READ) { + TEST_info("BIO_write_ex() failed %d, %d", retc, err); + TEST_openssl_errors(); + clienterr = 1; + } + + if (!servererr && rets <= 0) { + ossl_quic_tserver_tick(qtserv); + servererr = ossl_quic_tserver_is_term_any(qtserv); + if (!servererr) + rets = ossl_quic_tserver_is_handshake_confirmed(qtserv); + } + + if (clienterr && servererr) + goto err; + + if (++abortctr == MAXLOOPS) { + TEST_info("No progress made"); + goto err; + } + } while ((!retc && !clienterr) || (rets <= 0 && !servererr)); + + /* + * 2 loops: The first using the default stream, and the second using a new + * client initiated bidi stream. + */ + for (i = 0, thisbio = cbio; i < 2; i++) { + if (!TEST_true(ossl_quic_tserver_read(qtserv, sid, buf, sizeof(buf), + &readbytes)) + || !TEST_mem_eq(msg, msglen, buf, readbytes)) + goto err; + + if (!TEST_true(ossl_quic_tserver_write(qtserv, sid, (unsigned char *)msg, + msglen, &written))) + goto err; + ossl_quic_tserver_tick(qtserv); + + if (!TEST_true(BIO_read_ex(thisbio, buf, sizeof(buf), &readbytes)) + || !TEST_mem_eq(msg, msglen, buf, readbytes)) + goto err; + + if (i == 1) + break; + + /* + * Now create a new stream and repeat. The bottom two bits of the stream + * id represents whether the stream is bidi and whether it is client + * initiated or not. For client initiated bidi they are both 0. So the + * first client initiated bidi stream is 0 and the next one is 4. + */ + sid = 4; + stream = SSL_new_stream(clientquic, 0); + if (!TEST_ptr(stream)) + goto err; + + thisbio = strbio = BIO_new(BIO_f_ssl()); + if (!TEST_ptr(strbio)) + goto err; + + if (!TEST_int_eq(BIO_set_ssl(thisbio, stream, BIO_CLOSE), 1)) + goto err; + stream = NULL; + + if (!TEST_true(BIO_write_ex(thisbio, msg, msglen, &written))) + goto err; + + ossl_quic_tserver_tick(qtserv); + } + + testresult = 1; + err: + BIO_free_all(cbio); + BIO_free_all(strbio); + SSL_free(stream); + ossl_quic_tserver_free(qtserv); + SSL_CTX_free(cctx); + + return testresult; +} + OPT_TEST_DECLARE_USAGE("provider config certsdir datadir\n") int setup_tests(void) @@ -673,6 +806,7 @@ int setup_tests(void) ADD_TEST(test_quic_forbidden_apis); ADD_TEST(test_quic_forbidden_options); ADD_ALL_TESTS(test_quic_set_fd, 3); + ADD_TEST(test_bio_ssl); return 1; err: cleanup_tests();