]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Add a simple QUIC test for blocking mode
authorMatt Caswell <matt@openssl.org>
Mon, 13 Mar 2023 17:36:24 +0000 (17:36 +0000)
committerPauli <pauli@openssl.org>
Sun, 19 Mar 2023 22:35:55 +0000 (09:35 +1100)
We create "real" sockets for blocking mode so that we can block on them.

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/20514)

12 files changed:
doc/designs/quic-design/quic-fault-injector.md
include/internal/quic_tserver.h
ssl/quic/quic_tserver.c
test/build.info
test/helpers/quictestlib.c
test/helpers/quictestlib.h
test/helpers/ssltestlib.c
test/helpers/ssltestlib.h
test/quicapitest.c
test/quicfaultstest.c
test/recipes/75-test_quicapi.t
test/sslapitest.c

index 703ea9cdae5cab90e24a6aad6603b26135a96a80..2d7a5a9fa213e6f52d89256f563a030f8776a3e2 100644 (file)
@@ -210,9 +210,10 @@ typedef struct ossl_qf_encrypted_extensions {
 /*
  * Given an SSL_CTX for the client and filenames for the server certificate and
  * keyfile, create a server and client instances as well as a fault injector
- * instance
+ * instance. |block| indicates whether we are using blocking mode or not.
  */
-int qtest_create_quic_objects(SSL_CTX *clientctx, char *certfile, char *keyfile,
+int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx,
+                              char *certfile, char *keyfile, int block,
                               QUIC_TSERVER **qtserv, SSL **cssl,
                               OSSL_QUIC_FAULT **fault);
 
@@ -431,8 +432,8 @@ static int test_unknown_frame(void)
     if (!TEST_ptr(cctx))
         goto err;
 
-    if (!TEST_true(qtest_create_quic_objects(cctx, cert, privkey, &qtserv,
-                                             &cssl, &fault)))
+    if (!TEST_true(qtest_create_quic_objects(NULL, cctx, cert, privkey, 0,
+                                             &qtserv, &cssl, &fault)))
         goto err;
 
     if (!TEST_true(qtest_create_quic_connection(qtserv, cssl)))
@@ -524,8 +525,8 @@ static int test_no_transport_params(void)
     if (!TEST_ptr(cctx))
         goto err;
 
-    if (!TEST_true(qtest_create_quic_objects(cctx, cert, privkey, &qtserv,
-                                             &cssl, &fault)))
+    if (!TEST_true(qtest_create_quic_objects(NULL, cctx, cert, privkey, 0,
+                                             &qtserv, &cssl, &fault)))
         goto err;
 
     if (!TEST_true(ossl_quic_fault_set_hand_enc_ext_listener(fault,
index f53ec9ffbb343e04d02be1305704d577a6edd501..a7fbb393f2651dd69b81d7c1af2b6a62f9c0b092 100644 (file)
@@ -11,6 +11,7 @@
 # define OSSL_QUIC_TSERVER_H
 
 # include <openssl/ssl.h>
+# include <openssl/bio.h>
 # include "internal/quic_stream.h"
 # include "internal/quic_channel.h"
 # include "internal/statem.h"
@@ -109,6 +110,8 @@ int ossl_quic_tserver_write(QUIC_TSERVER *srv,
  */
 int ossl_quic_tserver_conclude(QUIC_TSERVER *srv);
 
+BIO *ossl_quic_tserver_get0_rbio(QUIC_TSERVER *srv);
+
 # endif
 
 #endif
index 0498bf8d0e7d58832ec8e7e543603f243f74c77b..8d11379d95bacea2769bc3fdbba53f20c833f141 100644 (file)
@@ -262,3 +262,8 @@ int ossl_quic_tserver_conclude(QUIC_TSERVER *srv)
     ossl_quic_tserver_tick(srv);
     return 1;
 }
+
+BIO *ossl_quic_tserver_get0_rbio(QUIC_TSERVER *srv)
+{
+    return srv->args.net_rbio;
+}
index 255aef27c0ee0a5b04abf13ba2a4e9de9433492d..dc3e4518ac42b8c2baf456c2e85eaf1396c02094 100644 (file)
@@ -71,7 +71,7 @@ IF[{- !$disabled{tests} -}]
   ENDIF
 
   IF[{- !$disabled{quic} -}]
-    PROGRAMS{noinst}=priority_queue_test event_queue_test quicfaultstest
+    PROGRAMS{noinst}=priority_queue_test event_queue_test quicfaultstest quicapitest
   ENDIF
 
   IF[{- !$disabled{comp} && (!$disabled{brotli} || !$disabled{zstd} || !$disabled{zlib}) -}]
@@ -799,9 +799,13 @@ IF[{- !$disabled{tests} -}]
       INCLUDE[event_queue_test]=../include ../apps/include
       DEPEND[event_queue_test]=../libcrypto ../libssl.a libtestutil.a
 
-      SOURCE[quicfaultstest]=quicfaultstest.c helpers/quictestlib.c
+      SOURCE[quicfaultstest]=quicfaultstest.c helpers/ssltestlib.c helpers/quictestlib.c
       INCLUDE[quicfaultstest]=../include ../apps/include ..
       DEPEND[quicfaultstest]=../libcrypto.a ../libssl.a libtestutil.a
+
+      SOURCE[quicapitest]=quicapitest.c helpers/ssltestlib.c helpers/quictestlib.c
+      INCLUDE[quicapitest]=../include ../apps/include
+      DEPEND[quicapitest]=../libcrypto.a ../libssl.a libtestutil.a
     ENDIF
 
     SOURCE[dhtest]=dhtest.c
@@ -1069,15 +1073,11 @@ ENDIF
   ENDIF
 
   IF[{- !$disabled{'quic'} -}]
-    PROGRAMS{noinst}=quicapitest quic_wire_test quic_ackm_test quic_record_test
+    PROGRAMS{noinst}=quic_wire_test quic_ackm_test quic_record_test
     PROGRAMS{noinst}=quic_fc_test quic_stream_test quic_cfq_test quic_txpim_test
     PROGRAMS{noinst}=quic_fifd_test quic_txp_test quic_tserver_test
   ENDIF
 
-  SOURCE[quicapitest]=quicapitest.c helpers/ssltestlib.c
-  INCLUDE[quicapitest]=../include ../apps/include
-  DEPEND[quicapitest]=../libcrypto ../libssl libtestutil.a
-
   SOURCE[quic_ackm_test]=quic_ackm_test.c
   INCLUDE[quic_ackm_test]=../include ../apps/include
   DEPEND[quic_ackm_test]=../libcrypto.a ../libssl.a libtestutil.a
index 657fcd257c591819da589a732221836ca31c85ea..e60573eb6e9535dfc0376537ea6b63a67e5d92e4 100644 (file)
@@ -8,9 +8,14 @@
  */
 
 #include <assert.h>
+#include <openssl/configuration.h>
 #include <openssl/bio.h>
 #include "quictestlib.h"
+#include "ssltestlib.h"
 #include "../testutil.h"
+#if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
+# include "../threadstest.h"
+#endif
 #include "internal/quic_wire_pkt.h"
 #include "internal/quic_record_tx.h"
 #include "internal/quic_error.h"
@@ -61,8 +66,9 @@ static void handshake_finish(void *arg);
 
 static BIO_METHOD *get_bio_method(void);
 
-int qtest_create_quic_objects(SSL_CTX *clientctx, char *certfile, char *keyfile,
-                              QUIC_TSERVER **qtserv, SSL **cssl,
+int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx,
+                              char *certfile, char *keyfile,
+                              int block, QUIC_TSERVER **qtserv, SSL **cssl,
                               QTEST_FAULT **fault)
 {
     /* ALPN value as recognised by QUIC_TSERVER */
@@ -79,28 +85,54 @@ int qtest_create_quic_objects(SSL_CTX *clientctx, char *certfile, char *keyfile,
     if (!TEST_ptr(*cssl))
         return 0;
 
-    if (!TEST_true(SSL_set_blocking_mode(*cssl, 0)))
-        goto err;
-
     /* SSL_set_alpn_protos returns 0 for success! */
     if (!TEST_false(SSL_set_alpn_protos(*cssl, alpn, sizeof(alpn))))
         goto err;
 
-    if (!TEST_true(BIO_new_bio_dgram_pair(&cbio, 0, &sbio, 0)))
+    if (!TEST_ptr(peeraddr = BIO_ADDR_new()))
         goto err;
 
-    if (!TEST_true(BIO_dgram_set_caps(cbio, BIO_DGRAM_CAP_HANDLES_DST_ADDR))
-            || !TEST_true(BIO_dgram_set_caps(sbio, BIO_DGRAM_CAP_HANDLES_DST_ADDR)))
+    if (block) {
+#if !defined(OPENSSL_NO_POSIX_IO)
+        int cfd, sfd;
+
+        /*
+         * For blocking mode we need to create actual sockets rather than doing
+         * everything in memory
+         */
+        if (!TEST_true(create_test_sockets(&cfd, &sfd, SOCK_DGRAM, peeraddr)))
+            goto err;
+        cbio = BIO_new_dgram(cfd, 1);
+        if (!TEST_ptr(cbio)) {
+            close(cfd);
+            close(sfd);
+            goto err;
+        }
+        sbio = BIO_new_dgram(sfd, 1);
+        if (!TEST_ptr(sbio)) {
+            close(sfd);
+            goto err;
+        }
+#else
         goto err;
+#endif
+    } else {
+        if (!TEST_true(BIO_new_bio_dgram_pair(&cbio, 0, &sbio, 0)))
+            goto err;
 
-    SSL_set_bio(*cssl, cbio, cbio);
+        if (!TEST_true(BIO_dgram_set_caps(cbio, BIO_DGRAM_CAP_HANDLES_DST_ADDR))
+                || !TEST_true(BIO_dgram_set_caps(sbio, BIO_DGRAM_CAP_HANDLES_DST_ADDR)))
+            goto err;
 
-    if (!TEST_ptr(peeraddr = BIO_ADDR_new()))
-        goto err;
+        /* Dummy server address */
+        if (!TEST_true(BIO_ADDR_rawmake(peeraddr, AF_INET, &ina, sizeof(ina),
+                                        htons(0))))
+            goto err;
+    }
+
+    SSL_set_bio(*cssl, cbio, cbio);
 
-    /* Dummy server address */
-    if (!TEST_true(BIO_ADDR_rawmake(peeraddr, AF_INET, &ina, sizeof(ina),
-                                    htons(0))))
+    if (!TEST_true(SSL_set_blocking_mode(*cssl, block)))
         goto err;
 
     if (!TEST_true(SSL_set_initial_peer_addr(*cssl, peeraddr)))
@@ -121,6 +153,7 @@ int qtest_create_quic_objects(SSL_CTX *clientctx, char *certfile, char *keyfile,
     if (!TEST_ptr(BIO_push(fisbio, sbio)))
         goto err;
 
+    tserver_args.libctx = libctx;
     tserver_args.net_rbio = sbio;
     tserver_args.net_wbio = fisbio;
 
@@ -144,6 +177,7 @@ int qtest_create_quic_objects(SSL_CTX *clientctx, char *certfile, char *keyfile,
     BIO_free(fisbio);
     BIO_free(sbio);
     SSL_free(*cssl);
+    *cssl = NULL;
     ossl_quic_tserver_free(*qtserv);
     if (fault != NULL)
         OPENSSL_free(*fault);
@@ -151,12 +185,66 @@ int qtest_create_quic_objects(SSL_CTX *clientctx, char *certfile, char *keyfile,
     return 0;
 }
 
+int qtest_supports_blocking(void)
+{
+#if !defined(OPENSSL_NO_POSIX_IO) && defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
+    return 1;
+#else
+    return 0;
+#endif
+}
+
 #define MAXLOOPS    1000
 
+#if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
+static int globserverret = 0;
+static QUIC_TSERVER *globtserv;
+static const thread_t thread_zero;
+
+static void run_server_thread(void)
+{
+    /*
+     * This will operate in a busy loop because the server does not block,
+     * but should be acceptable because it is local and we expect this to be
+     * fast
+     */
+    globserverret = qtest_create_quic_connection(globtserv, NULL);
+}
+#endif
+
 int qtest_create_quic_connection(QUIC_TSERVER *qtserv, SSL *clientssl)
 {
     int retc = -1, rets = 0, err, abortctr = 0, ret = 0;
     int clienterr = 0, servererr = 0;
+#if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
+    /*
+     * Pointless initialisation to avoid bogus compiler warnings about using
+     * t uninitialised
+     */
+    thread_t t = thread_zero;
+#endif
+
+    if (!TEST_ptr(qtserv)) {
+        goto err;
+    } else if (clientssl == NULL) {
+        retc = 1;
+    } else if (SSL_get_blocking_mode(clientssl) > 0) {
+#if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
+        /*
+         * clientssl is blocking. We will need a thread to complete the
+         * connection
+         */
+        globtserv = qtserv;
+        if (!TEST_true(run_thread(&t, run_server_thread)))
+            goto err;
+
+        qtserv = NULL;
+        rets = 1;
+#else
+        TEST_error("No thread support in this build");
+        goto err;
+#endif
+    }
 
     do {
         err = SSL_ERROR_WANT_WRITE;
@@ -191,18 +279,37 @@ int qtest_create_quic_connection(QUIC_TSERVER *qtserv, SSL *clientssl)
         if (clienterr && servererr)
             goto err;
 
-        if (++abortctr == MAXLOOPS) {
+        if (clientssl != NULL && ++abortctr == MAXLOOPS) {
             TEST_info("No progress made");
             goto err;
         }
     } while ((retc <= 0 && !clienterr) || (rets <= 0 && !servererr));
 
+    if (qtserv == NULL && rets > 0) {
+#if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
+        if (!TEST_true(wait_for_thread(t)) || !TEST_true(globserverret))
+            goto err;
+#else
+        TEST_error("Should not happen");
+        goto err;
+#endif
+    }
+
     if (!clienterr && !servererr)
         ret = 1;
  err:
     return ret;
 }
 
+int qtest_shutdown(QUIC_TSERVER *qtserv, SSL *clientssl)
+{
+    /* Busy loop in non-blocking mode. It should be quick because its local */
+    while (SSL_shutdown(clientssl) != 1)
+        ossl_quic_tserver_tick(qtserv);
+
+    return 1;
+}
+
 int qtest_check_server_transport_err(QUIC_TSERVER *qtserv, uint64_t code)
 {
     QUIC_TERMINATE_CAUSE cause;
index 165551aa6a3ae7257103de4cc02cd1fdb38f3dfd..71cdd91bcb16dd36a16c25d76df674aee18ad8e5 100644 (file)
@@ -27,9 +27,10 @@ typedef struct qtest_fault_encrypted_extensions {
 /*
  * Given an SSL_CTX for the client and filenames for the server certificate and
  * keyfile, create a server and client instances as well as a fault injector
- * instance
+ * instance. |block| indicates whether we are using blocking mode or not.
  */
-int qtest_create_quic_objects(SSL_CTX *clientctx, char *certfile, char *keyfile,
+int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx,
+                              char *certfile, char *keyfile, int block,
                               QUIC_TSERVER **qtserv, SSL **cssl,
                               QTEST_FAULT **fault);
 
@@ -38,12 +39,20 @@ int qtest_create_quic_objects(SSL_CTX *clientctx, char *certfile, char *keyfile,
  */
 void qtest_fault_free(QTEST_FAULT *fault);
 
+/* Returns 1 if the quictestlib supports blocking tests */
+int qtest_supports_blocking(void);
+
 /*
  * Run the TLS handshake to create a QUIC connection between the client and
  * server.
  */
 int qtest_create_quic_connection(QUIC_TSERVER *qtserv, SSL *clientssl);
 
+/*
+ * Shutdown the client SSL object gracefully
+ */
+int qtest_shutdown(QUIC_TSERVER *qtserv, SSL *clientssl);
+
 /*
  * Confirm that the server has received the given transport error code.
  */
index 727ba7ff6ae279349df7e95b7ccd6044f01d2702..94100b9ca4ece370569f55457317c84cf5be1e61 100644 (file)
@@ -9,20 +9,15 @@
 
 #include <string.h>
 
+#include "internal/e_os.h"
 #include "internal/nelem.h"
 #include "ssltestlib.h"
 #include "../testutil.h"
 
-#ifdef OPENSSL_SYS_UNIX
-# include <unistd.h>
-# ifndef OPENSSL_NO_KTLS
-#  include <netinet/in.h>
-#  include <netinet/in.h>
-#  include <arpa/inet.h>
-#  include <sys/socket.h>
-#  include <unistd.h>
-#  include <fcntl.h>
-# endif
+#if (!defined(OPENSSL_NO_KTLS) || !defined(OPENSSL_NO_QUIC)) && !defined(OPENSSL_NO_POSIX_IO) && !defined(OPENSSL_NO_SOCK)
+# define OSSL_USE_SOCKETS 1
+# include "internal/sockets.h"
+# include <openssl/bio.h>
 #endif
 
 static int tls_dump_new(BIO *bi);
@@ -879,19 +874,25 @@ int create_ssl_ctx_pair(OSSL_LIB_CTX *libctx, const SSL_METHOD *sm,
 
 #define MAXLOOPS    1000000
 
-#if !defined(OPENSSL_NO_KTLS) && !defined(OPENSSL_NO_SOCK)
-static int set_nb(int fd)
+#if defined(OSSL_USE_SOCKETS)
+int wait_until_sock_readable(int sock)
 {
-    int flags;
+    fd_set readfds;
+    struct timeval timeout;
+    int width;
+
+    width = sock + 1;
+    FD_ZERO(&readfds);
+    openssl_fdset(sock, &readfds);
+    timeout.tv_sec = 10; /* give up after 10 seconds */
+    timeout.tv_usec = 0;
+
+    select(width, &readfds, NULL, NULL, &timeout);
 
-    flags = fcntl(fd, F_GETFL, 0);
-    if (flags == -1)
-        return flags;
-    flags = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
-    return flags;
+    return FD_ISSET(sock, &readfds);
 }
 
-int create_test_sockets(int *cfdp, int *sfdp)
+int create_test_sockets(int *cfdp, int *sfdp, int socktype, BIO_ADDR *saddr)
 {
     struct sockaddr_in sin;
     const char *host = "127.0.0.1";
@@ -903,8 +904,9 @@ int create_test_sockets(int *cfdp, int *sfdp)
     sin.sin_family = AF_INET;
     sin.sin_addr.s_addr = inet_addr(host);
 
-    afd = socket(AF_INET, SOCK_STREAM, 0);
-    if (afd < 0)
+    afd = BIO_socket(AF_INET, socktype,
+                     socktype == SOCK_STREAM ? IPPROTO_TCP : IPPROTO_UDP, 0);
+    if (afd == INVALID_SOCKET)
         return 0;
 
     if (bind(afd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
@@ -913,16 +915,32 @@ int create_test_sockets(int *cfdp, int *sfdp)
     if (getsockname(afd, (struct sockaddr*)&sin, &slen) < 0)
         goto out;
 
-    if (listen(afd, 1) < 0)
+    if (saddr != NULL
+            && !BIO_ADDR_rawmake(saddr, sin.sin_family, &sin.sin_addr,
+                                 sizeof(sin.sin_addr), sin.sin_port))
+        goto out;
+
+    if (socktype == SOCK_STREAM && listen(afd, 1) < 0)
         goto out;
 
-    cfd = socket(AF_INET, SOCK_STREAM, 0);
-    if (cfd < 0)
+    cfd = BIO_socket(AF_INET, socktype,
+                     socktype == SOCK_STREAM ? IPPROTO_TCP : IPPROTO_UDP, 0);
+    if (cfd == INVALID_SOCKET)
         goto out;
 
-    if (set_nb(afd) == -1)
+    if (!BIO_socket_nbio(afd, 1))
         goto out;
 
+    /*
+     * If a DGRAM socket then we don't call "accept" or "connect" - so act like
+     * we already called them.
+     */
+    if (socktype == SOCK_DGRAM) {
+        cfd_connected = 1;
+        sfd = afd;
+        afd = -1;
+    }
+
     while (sfd == -1 || !cfd_connected) {
         sfd = accept(afd, NULL, 0);
         if (sfd == -1 && errno != EAGAIN)
@@ -934,7 +952,7 @@ int create_test_sockets(int *cfdp, int *sfdp)
             cfd_connected = 1;
     }
 
-    if (set_nb(cfd) == -1 || set_nb(sfd) == -1)
+    if (!BIO_socket_nbio(cfd, 1) || !BIO_socket_nbio(sfd, 1))
         goto out;
     ret = 1;
     *cfdp = cfd;
@@ -984,7 +1002,7 @@ int create_ssl_objects2(SSL_CTX *serverctx, SSL_CTX *clientctx, SSL **sssl,
     BIO_free(c_to_s_bio);
     return 0;
 }
-#endif
+#endif /* defined(OSSL_USE_SOCKETS) */
 
 /*
  * NOTE: Transfers control of the BIOs - this function will free them on error
index d8ee6a9b7d04d639c3cc4d279e5e1f61d53cae38..bc06813e725785119715bff150d7139855c10e13 100644 (file)
@@ -22,7 +22,8 @@ int create_bare_ssl_connection(SSL *serverssl, SSL *clientssl, int want,
                                int read, int listen);
 int create_ssl_objects2(SSL_CTX *serverctx, SSL_CTX *clientctx, SSL **sssl,
                        SSL **cssl, int sfd, int cfd);
-int create_test_sockets(int *cfd, int *sfd);
+int wait_until_sock_readable(int sock);
+int create_test_sockets(int *cfdp, int *sfdp, int socktype, BIO_ADDR *saddr);
 int create_ssl_connection(SSL *serverssl, SSL *clientssl, int want);
 void shutdown_ssl_connection(SSL *serverssl, SSL *clientssl);
 
index a550f636f1fc66f6dcb88a23bfd3e0edb7faa350..487e6fa9364b079c43e97b8e3b4f353af5e2d2cc 100644 (file)
 #include <openssl/quic.h>
 
 #include "helpers/ssltestlib.h"
+#include "helpers/quictestlib.h"
 #include "testutil.h"
 #include "testutil/output.h"
 
 static OSSL_LIB_CTX *libctx = NULL;
 static OSSL_PROVIDER *defctxnull = NULL;
+static char *certsdir = NULL;
+static char *cert = NULL;
+static char *privkey = NULL;
 
 static int is_fips = 0;
 
-#if 0
-/* TODO(QUIC): Temporarily disabled during front-end I/O API finalization. */
-
 /*
  * Test that we read what we've written.
+ * Test 0: Non-blocking
+ * Test 1: Blocking
  */
-static int test_quic_write_read(void)
+static int test_quic_write_read(int idx)
 {
-    SSL_CTX *cctx = NULL, *sctx = NULL;
-    SSL *clientquic = NULL, *serverquic = NULL;
+    SSL_CTX *cctx = SSL_CTX_new_ex(libctx, NULL, OSSL_QUIC_client_method());
+    SSL *clientquic = NULL;
+    QUIC_TSERVER *qtserv = NULL;
     int j, ret = 0;
-    char buf[20];
+    unsigned char buf[20];
     static char *msg = "A test message";
     size_t msglen = strlen(msg);
     size_t numbytes = 0;
+    int ssock = 0, csock = 0;
+
+    if (idx == 1 && !qtest_supports_blocking())
+        return TEST_skip("Blocking tests not supported in this build");
 
-    if (!TEST_true(create_ssl_ctx_pair(libctx, OSSL_QUIC_server_method(),
-                                       OSSL_QUIC_client_method(),
-                                       0,
-                                       0,
-                                       &sctx, &cctx, NULL, NULL))
-            || !TEST_true(create_ssl_objects(sctx, cctx, &serverquic, &clientquic,
-                                             NULL, NULL))
-            || !TEST_true(create_bare_ssl_connection(serverquic, clientquic,
-                                                     SSL_ERROR_NONE, 0, 0)))
+    if (!TEST_ptr(cctx)
+            || !TEST_true(qtest_create_quic_objects(libctx, cctx, cert, privkey,
+                                                    idx, &qtserv, &clientquic,
+                                                    NULL))
+            || !TEST_true(SSL_set_tlsext_host_name(clientquic, "localhost"))
+            || !TEST_true(qtest_create_quic_connection(qtserv, clientquic)))
         goto end;
 
+    if (idx == 1) {
+        if (!TEST_true(BIO_get_fd(ossl_quic_tserver_get0_rbio(qtserv), &ssock)))
+            goto end;
+        if (!TEST_int_gt(csock = SSL_get_rfd(clientquic), 0))
+            goto end;
+    }
+
     for (j = 0; j < 2; j++) {
         /* Check that sending and receiving app data is ok */
-        if (!TEST_true(SSL_write_ex(clientquic, msg, msglen, &numbytes))
-                || !TEST_true(SSL_read_ex(serverquic, buf, sizeof(buf),
-                                          &numbytes))
+        if (!TEST_true(SSL_write_ex(clientquic, msg, msglen, &numbytes)))
+            goto end;
+        if (idx == 1 && !TEST_true(wait_until_sock_readable(ssock)))
+            goto end;
+        ossl_quic_tserver_tick(qtserv);
+        if (!TEST_true(ossl_quic_tserver_read(qtserv, buf, sizeof(buf),
+                                                     &numbytes))
                 || !TEST_mem_eq(buf, numbytes, msg, msglen))
             goto end;
 
-        if (!TEST_true(SSL_write_ex(serverquic, msg, msglen, &numbytes))
-                || !TEST_true(SSL_read_ex(clientquic, buf, sizeof(buf),
-                                          &numbytes))
-                || !TEST_mem_eq(buf, numbytes, msg, msglen))
+        if (!TEST_true(ossl_quic_tserver_write(qtserv, (unsigned char *)msg,
+                                               msglen, &numbytes)))
+            goto end;
+        ossl_quic_tserver_tick(qtserv);
+        SSL_tick(clientquic);
+        /*
+         * In blocking mode the SSL_read_ex call will block until the socket is
+         * readable and has our data. In non-blocking mode we're doing everything
+         * in memory, so it should be immediately available
+         */
+        if (!TEST_true(SSL_read_ex(clientquic, buf, 1, &numbytes))
+                || !TEST_size_t_eq(numbytes, 1)
+                || !TEST_true(SSL_has_pending(clientquic))
+                || !TEST_int_eq(SSL_pending(clientquic), msglen - 1)
+                || !TEST_true(SSL_read_ex(clientquic, buf + 1, sizeof(buf) - 1, &numbytes))
+                || !TEST_mem_eq(buf, numbytes + 1, msg, msglen))
             goto end;
     }
 
+    if (!TEST_true(qtest_shutdown(qtserv, clientquic)))
+        goto end;
+
     ret = 1;
 
  end:
-    SSL_free(serverquic);
+    ossl_quic_tserver_free(qtserv);
     SSL_free(clientquic);
-    SSL_CTX_free(sctx);
     SSL_CTX_free(cctx);
 
     return ret;
 }
-#endif
 
 /* Test that a vanilla QUIC SSL object has the expected ciphersuites available */
 static int test_ciphersuites(void)
@@ -144,43 +173,54 @@ int setup_tests(void)
      */
     if (!TEST_false(OSSL_PROVIDER_available(NULL, "default"))
             || !TEST_false(OSSL_PROVIDER_available(NULL, "fips")))
-        return 0;
+        goto err;
 
     if (!test_skip_common_options()) {
         TEST_error("Error parsing test options\n");
-        return 0;
+        goto err;
     }
 
     if (!TEST_ptr(modulename = test_get_argument(0))
-            || !TEST_ptr(configfile = test_get_argument(1)))
-        return 0;
+            || !TEST_ptr(configfile = test_get_argument(1))
+            || !TEST_ptr(certsdir = test_get_argument(2)))
+        goto err;
 
     if (!TEST_true(OSSL_LIB_CTX_load_config(libctx, configfile)))
-        return 0;
+        goto err;
 
     /* Check we have the expected provider available */
     if (!TEST_true(OSSL_PROVIDER_available(libctx, modulename)))
-        return 0;
+        goto err;
 
     /* Check the default provider is not available */
     if (strcmp(modulename, "default") != 0
             && !TEST_false(OSSL_PROVIDER_available(libctx, "default")))
-        return 0;
+        goto err;
 
     if (strcmp(modulename, "fips") == 0)
         is_fips = 1;
 
-    /* TODO(QUIC): Temporarily disabled during front-end I/O API finalization. */
-#if 0
-    ADD_TEST(test_quic_write_read);
-#endif
+    cert = test_mk_file_path(certsdir, "servercert.pem");
+    if (cert == NULL)
+        goto err;
+
+    privkey = test_mk_file_path(certsdir, "serverkey.pem");
+    if (privkey == NULL)
+        goto err;
+
+    ADD_ALL_TESTS(test_quic_write_read, 2);
     ADD_TEST(test_ciphersuites);
 
     return 1;
+ err:
+    cleanup_tests();
+    return 0;
 }
 
 void cleanup_tests(void)
 {
+    OPENSSL_free(cert);
+    OPENSSL_free(privkey);
     OSSL_PROVIDER_unload(defctxnull);
     OSSL_LIB_CTX_free(libctx);
 }
index 23ccc1e122ca94086b6a6ad2ee4118cb3182a773..beb3e4dc41319dfb53bac483f0c0f310baf59515 100644 (file)
@@ -34,8 +34,8 @@ static int test_basic(void)
     if (!TEST_ptr(cctx))
         goto err;
 
-    if (!TEST_true(qtest_create_quic_objects(cctx, cert, privkey, &qtserv,
-                                             &cssl, NULL)))
+    if (!TEST_true(qtest_create_quic_objects(NULL, cctx, cert, privkey, 0,
+                                             &qtserv, &cssl, NULL)))
         goto err;
 
     if (!TEST_true(qtest_create_quic_connection(qtserv, cssl)))
@@ -103,8 +103,8 @@ static int test_unknown_frame(void)
     if (!TEST_ptr(cctx))
         goto err;
 
-    if (!TEST_true(qtest_create_quic_objects(cctx, cert, privkey, &qtserv,
-                                             &cssl, &fault)))
+    if (!TEST_true(qtest_create_quic_objects(NULL, cctx, cert, privkey, 0,
+                                             &qtserv, &cssl, &fault)))
         goto err;
 
     if (!TEST_true(qtest_create_quic_connection(qtserv, cssl)))
@@ -189,8 +189,8 @@ static int test_no_transport_params(void)
     if (!TEST_ptr(cctx))
         goto err;
 
-    if (!TEST_true(qtest_create_quic_objects(cctx, cert, privkey, &qtserv,
-                                             &cssl, &fault)))
+    if (!TEST_true(qtest_create_quic_objects(NULL, cctx, cert, privkey, 0,
+                                             &qtserv, &cssl, &fault)))
         goto err;
 
     if (!TEST_true(qtest_fault_set_hand_enc_ext_listener(fault,
@@ -267,8 +267,8 @@ static int test_corrupted_data(int idx)
     if (!TEST_ptr(cctx))
         goto err;
 
-    if (!TEST_true(qtest_create_quic_objects(cctx, cert, privkey, &qtserv,
-                                             &cssl, &fault)))
+    if (!TEST_true(qtest_create_quic_objects(NULL, cctx, cert, privkey, 0,
+                                             &qtserv, &cssl, &fault)))
         goto err;
 
     if (idx == 0) {
index 6e96d458ed5e2a685e3516e7b5ea41de8c058f49..451fb4efd4c687cf66f5756b563da6f594171542 100644 (file)
@@ -27,11 +27,12 @@ plan tests =>
     + 1;                        # quicapitest with default provider
 
 ok(run(test(["quicapitest", "default",
-             srctop_file("test", "default.cnf")])),
+             srctop_file("test", "default.cnf"), srctop_dir("test", "certs")])),
              "running quicapitest");
 
 unless ($no_fips) {
     ok(run(test(["quicapitest", "fips",
-                 srctop_file("test", "fips-and-base.cnf")])),
+                 srctop_file("test", "fips-and-base.cnf"),
+                 srctop_dir("test", "certs")])),
                  "running quicapitest");
 }
index 102b590aaee5fed1466312d511af0661405c9c41..9cf4cf7d35636439c838099115c4f8739adf831c 100644 (file)
@@ -1172,7 +1172,7 @@ static int execute_test_ktls(int cis_ktls, int sis_ktls,
     int rx_supported;
     SSL_CONNECTION *clientsc, *serversc;
 
-    if (!TEST_true(create_test_sockets(&cfd, &sfd)))
+    if (!TEST_true(create_test_sockets(&cfd, &sfd, SOCK_STREAM, NULL)))
         goto end;
 
     /* Skip this test if the platform does not support ktls */
@@ -1317,7 +1317,7 @@ static int execute_test_ktls_sendfile(int tls_version, const char *cipher,
     buf = OPENSSL_zalloc(SENDFILE_SZ);
     buf_dst = OPENSSL_zalloc(SENDFILE_SZ);
     if (!TEST_ptr(buf) || !TEST_ptr(buf_dst)
-        || !TEST_true(create_test_sockets(&cfd, &sfd)))
+        || !TEST_true(create_test_sockets(&cfd, &sfd, SOCK_STREAM, NULL)))
         goto end;
 
     /* Skip this test if the platform does not support ktls */