]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Extend the test_quic_write_read() test to include resumption
authorMatt Caswell <matt@openssl.org>
Fri, 28 Jul 2023 14:32:57 +0000 (15:32 +0100)
committerHugo Landau <hlandau@openssl.org>
Wed, 2 Aug 2023 19:27:07 +0000 (20:27 +0100)
We add an additional loop around test_quic_write_read() to repeat the
test but using a session obtained from the initial iteration to confirm
that we can successfully resume the session.

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Hugo Landau <hlandau@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/21591)

doc/designs/quic-design/quic-fault-injector.md
test/helpers/quictestlib.c
test/helpers/quictestlib.h
test/quic_newcid_test.c
test/quicapitest.c
test/quicfaultstest.c

index 77e034df4d99c75376b91e0110f860646af8dc69..b77e2526c271a118a82c7e6fcba7687a2508d0e5 100644 (file)
@@ -213,8 +213,8 @@ typedef struct ossl_qf_encrypted_extensions {
  * instance. |block| indicates whether we are using blocking mode or not.
  */
 int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx,
-                              char *certfile, char *keyfile, int block,
-                              QUIC_TSERVER **qtserv, SSL **cssl,
+                              SSL_CTX *serverctx, char *certfile, char *keyfile,
+                              int block, QUIC_TSERVER **qtserv, SSL **cssl,
                               OSSL_QUIC_FAULT **fault);
 
 /*
@@ -432,7 +432,7 @@ static int test_unknown_frame(void)
     if (!TEST_ptr(cctx))
         goto err;
 
-    if (!TEST_true(qtest_create_quic_objects(NULL, cctx, cert, privkey, 0,
+    if (!TEST_true(qtest_create_quic_objects(NULL, cctx, NULL, cert, privkey, 0,
                                              &qtserv, &cssl, &fault)))
         goto err;
 
@@ -525,7 +525,7 @@ static int test_no_transport_params(void)
     if (!TEST_ptr(cctx))
         goto err;
 
-    if (!TEST_true(qtest_create_quic_objects(NULL, cctx, cert, privkey, 0,
+    if (!TEST_true(qtest_create_quic_objects(NULL, cctx, NULL, cert, privkey, 0,
                                              &qtserv, &cssl, &fault)))
         goto err;
 
index 98785e3306928e8a8ca232455bca5d265178b023..d081b121e856768e55b5d04bc0e7cf8fa9f47081 100644 (file)
@@ -72,7 +72,7 @@ static OSSL_TIME fake_now_cb(void *arg)
 }
 
 int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx,
-                              char *certfile, char *keyfile,
+                              SSL_CTX *serverctx, char *certfile, char *keyfile,
                               int flags, QUIC_TSERVER **qtserv, SSL **cssl,
                               QTEST_FAULT **fault)
 {
@@ -166,7 +166,9 @@ int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx,
     tserver_args.net_rbio = sbio;
     tserver_args.net_wbio = fisbio;
     tserver_args.alpn = NULL;
-    tserver_args.ctx = NULL;
+    if (serverctx != NULL && !TEST_true(SSL_CTX_up_ref(serverctx)))
+        goto err;
+    tserver_args.ctx = serverctx;
     if ((flags & QTEST_FLAG_FAKE_TIME) != 0) {
         fake_now = ossl_time_zero();
         tserver_args.now_cb = fake_now_cb;
@@ -187,6 +189,7 @@ int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx,
 
     return 1;
  err:
+    SSL_CTX_free(tserver_args.ctx);
     BIO_ADDR_free(peeraddr);
     BIO_free(cbio);
     BIO_free(fisbio);
index ee047bde0b5feeaa035631319f6b88e125789869..c4572db4cc7054333922b81d216f895cd649b754 100644 (file)
@@ -37,8 +37,8 @@ typedef struct qtest_fault_encrypted_extensions {
  * instance. |flags| is the logical or of flags defined above, or 0 if none.
  */
 int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx,
-                              char *certfile, char *keyfile, int flags,
-                              QUIC_TSERVER **qtserv, SSL **cssl,
+                              SSL_CTX *serverctx, char *certfile, char *keyfile,
+                              int flags, QUIC_TSERVER **qtserv, SSL **cssl,
                               QTEST_FAULT **fault);
 
 /* Where QTEST_FLAG_FAKE_TIME is used, add millis to the current time */
index 127439ff2a321ab31d24a035b141233146961d8f..cda55abca3cd3c6292bb1cebba99a42846b51f76 100644 (file)
@@ -67,7 +67,7 @@ static int test_ncid_frame(int fail)
     if (!TEST_ptr(cctx))
         goto err;
 
-    if (!TEST_true(qtest_create_quic_objects(NULL, cctx, cert, privkey, 0,
+    if (!TEST_true(qtest_create_quic_objects(NULL, cctx, NULL, cert, privkey, 0,
                                              &qtserv, &cssl, &fault)))
         goto err;
 
index f5c82733827d0623da1b23d1d375bae1a3bea6c3..3267b1b283c61096c6a9ddb8548166131948f2ee 100644 (file)
@@ -46,108 +46,164 @@ static int is_fips = 0;
 static int test_quic_write_read(int idx)
 {
     SSL_CTX *cctx = SSL_CTX_new_ex(libctx, NULL, OSSL_QUIC_client_method());
+    SSL_CTX *sctx = NULL;
     SSL *clientquic = NULL;
     QUIC_TSERVER *qtserv = NULL;
-    int j, ret = 0;
+    int j, k, ret = 0;
     unsigned char buf[20];
     static char *msg = "A test message";
     size_t msglen = strlen(msg);
     size_t numbytes = 0;
     int ssock = 0, csock = 0;
     uint64_t sid = UINT64_MAX;
+    SSL_SESSION *sess = NULL;
 
     if (idx >= 1 && !qtest_supports_blocking())
         return TEST_skip("Blocking tests not supported in this build");
 
-    if (!TEST_ptr(cctx)
-            || !TEST_true(qtest_create_quic_objects(libctx, cctx, cert, privkey,
-                                                    idx >= 1 ? QTEST_FLAG_BLOCK : 0,
-                                                    &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)))
+    for (k = 0; k < 2; k++) {
+        if (!TEST_ptr(cctx)
+                || !TEST_true(qtest_create_quic_objects(libctx, cctx, sctx,
+                                                        cert, privkey,
+                                                        idx >= 1
+                                                            ? QTEST_FLAG_BLOCK
+                                                            : 0,
+                                                        &qtserv, &clientquic,
+                                                        NULL))
+                || !TEST_true(SSL_set_tlsext_host_name(clientquic, "localhost")))
             goto end;
-        if (!TEST_int_gt(csock = SSL_get_rfd(clientquic), 0))
-            goto end;
-    }
 
-    sid = 0; /* client-initiated bidirectional stream */
+        if (sess != NULL && !TEST_true(SSL_set_session(clientquic, sess)))
+            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_size_t_eq(numbytes, msglen))
+        if (!TEST_true(qtest_create_quic_connection(qtserv, clientquic)))
             goto end;
+
         if (idx >= 1) {
-            do {
-                if (!TEST_true(wait_until_sock_readable(ssock)))
+            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;
+        }
+
+        sid = 0; /* client-initiated bidirectional stream */
+
+        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_size_t_eq(numbytes, msglen))
+                goto end;
+            if (idx >= 1) {
+                do {
+                    if (!TEST_true(wait_until_sock_readable(ssock)))
+                        goto end;
+
+                    ossl_quic_tserver_tick(qtserv);
+
+                    if (!TEST_true(ossl_quic_tserver_read(qtserv, sid, buf,
+                                                          sizeof(buf),
+                                                          &numbytes)))
+                        goto end;
+                } while (numbytes == 0);
+
+                if (!TEST_mem_eq(buf, numbytes, msg, msglen))
                     goto end;
+            }
 
-                ossl_quic_tserver_tick(qtserv);
+            if (idx >= 2 && j > 0)
+                /* Introduce permanent socket error */
+                BIO_closesocket(csock);
 
-                if (!TEST_true(ossl_quic_tserver_read(qtserv, sid, buf, sizeof(buf),
-                                                      &numbytes)))
+            ossl_quic_tserver_tick(qtserv);
+            if (!TEST_true(ossl_quic_tserver_write(qtserv, sid,
+                                                   (unsigned char *)msg,
+                                                   msglen, &numbytes)))
+                goto end;
+            ossl_quic_tserver_tick(qtserv);
+            SSL_handle_events(clientquic);
+
+            if (idx >= 2 && j > 0) {
+                if (!TEST_false(SSL_read_ex(clientquic, buf, 1, &numbytes))
+                        || !TEST_int_eq(SSL_get_error(clientquic, 0),
+                                        SSL_ERROR_SYSCALL)
+                        || !TEST_false(SSL_write_ex(clientquic, msg, msglen,
+                                                    &numbytes))
+                        || !TEST_int_eq(SSL_get_error(clientquic, 0),
+                                        SSL_ERROR_SYSCALL))
                     goto end;
-            } while (numbytes == 0);
+                break;
+            }
 
-            if (!TEST_mem_eq(buf, numbytes, msg, msglen))
+            /*
+            * 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 (idx >= 2 && j > 0)
-            /* Introduce permanent socket error */
-            BIO_closesocket(csock);
+        if (sess == NULL) {
+            /* We didn't supply a session so we're not expecting resumption */
+            if (!TEST_false(SSL_session_reused(clientquic)))
+                goto end;
+            /* We should have a session ticket by now */
+            sess = SSL_get1_session(clientquic);
+            if (!TEST_ptr(sess))
+                goto end;
+        } else {
+            /* We supplied a session so we should have resumed */
+            if (!TEST_true(SSL_session_reused(clientquic)))
+                goto end;
+        }
 
-        ossl_quic_tserver_tick(qtserv);
-        if (!TEST_true(ossl_quic_tserver_write(qtserv, sid, (unsigned char *)msg,
-                                               msglen, &numbytes)))
-            goto end;
-        ossl_quic_tserver_tick(qtserv);
-        SSL_handle_events(clientquic);
-
-        if (idx >= 2 && j > 0) {
-            if (!TEST_false(SSL_read_ex(clientquic, buf, 1, &numbytes))
-                    || !TEST_int_eq(SSL_get_error(clientquic, 0),
-                                    SSL_ERROR_SYSCALL)
-                    || !TEST_false(SSL_write_ex(clientquic, msg, msglen,
-                                                &numbytes))
-                    || !TEST_int_eq(SSL_get_error(clientquic, 0),
-                                    SSL_ERROR_SYSCALL))
+        if (idx < 1) {
+            /*
+            * Blocking SSL_shutdown cannot be tested here due to requirement to
+            * tick TSERVER during drainage.
+            */
+            if (!TEST_true(qtest_shutdown(qtserv, clientquic)))
                 goto end;
-            break;
+        } else {
+            /*
+             * We cheat here because we have not shutdown correctly. We make the
+             * client think it has been shutdown normally so the session is
+             * eligible for reuse.
+             */
+            SSL_CONNECTION_FROM_SSL(clientquic)->shutdown = SSL_SENT_SHUTDOWN;
         }
 
-        /*
-         * 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 (sctx == NULL) {
+            sctx = ossl_quic_tserver_get0_ssl_ctx(qtserv);
+            if (!TEST_true(SSL_CTX_up_ref(sctx))) {
+                sctx = NULL;
+                goto end;
+            }
+        }
+        ossl_quic_tserver_free(qtserv);
+        qtserv = NULL;
+        SSL_free(clientquic);
+        clientquic = NULL;
 
-    if (idx < 1)
-        /*
-         * Blocking SSL_shutdown cannot be tested here due to requirement to
-         * tick TSERVER during drainage.
-         */
-        if (!TEST_true(qtest_shutdown(qtserv, clientquic)))
-            goto end;
+        if (idx >= 2)
+            break;
+    }
 
     ret = 1;
 
  end:
+    SSL_SESSION_free(sess);
     ossl_quic_tserver_free(qtserv);
     SSL_free(clientquic);
     SSL_CTX_free(cctx);
+    SSL_CTX_free(sctx);
 
     return ret;
 }
@@ -215,9 +271,9 @@ static int test_version(void)
     int testresult = 0;
 
     if (!TEST_ptr(cctx)
-            || !TEST_true(qtest_create_quic_objects(libctx, cctx, cert, privkey,
-                                                    0, &qtserv, &clientquic,
-                                                    NULL))
+            || !TEST_true(qtest_create_quic_objects(libctx, cctx, NULL, cert,
+                                                    privkey, 0, &qtserv,
+                                                    &clientquic, NULL))
             || !TEST_true(qtest_create_quic_connection(qtserv, clientquic)))
         goto err;
 
@@ -321,9 +377,9 @@ static int test_ssl_trace(void)
 
     if (!TEST_ptr(cctx)
             || !TEST_ptr(bio)
-            || !TEST_true(qtest_create_quic_objects(libctx, cctx, cert, privkey,
-                                                    0, &qtserv, &clientquic,
-                                                    NULL)))
+            || !TEST_true(qtest_create_quic_objects(libctx, cctx, NULL, cert,
+                                                    privkey, 0, &qtserv,
+                                                    &clientquic, NULL)))
         goto err;
 
     SSL_set_msg_callback(clientquic, SSL_trace);
@@ -649,7 +705,7 @@ static int test_bio_ssl(void)
     if (!TEST_int_eq(BIO_get_ssl(cbio, &clientquic), 1))
         goto err;
 
-    if (!TEST_true(qtest_create_quic_objects(libctx, NULL, cert, privkey,
+    if (!TEST_true(qtest_create_quic_objects(libctx, NULL, NULL, cert, privkey,
                                              0, &qtserv, &clientquic, NULL)))
         goto err;
 
index af1bc1b2dee1a73672d99aafdedd42ffe106f8f4..68e5cad8a0acfb818e3bdbde1513b8c3c64e6220 100644 (file)
@@ -34,7 +34,7 @@ static int test_basic(void)
     if (!TEST_ptr(cctx))
         goto err;
 
-    if (!TEST_true(qtest_create_quic_objects(NULL, cctx, cert, privkey, 0,
+    if (!TEST_true(qtest_create_quic_objects(NULL, cctx, NULL, cert, privkey, 0,
                                              &qtserv, &cssl, NULL)))
         goto err;
 
@@ -104,7 +104,7 @@ static int test_unknown_frame(void)
     if (!TEST_ptr(cctx))
         goto err;
 
-    if (!TEST_true(qtest_create_quic_objects(NULL, cctx, cert, privkey, 0,
+    if (!TEST_true(qtest_create_quic_objects(NULL, cctx, NULL, cert, privkey, 0,
                                              &qtserv, &cssl, &fault)))
         goto err;
 
@@ -184,7 +184,7 @@ static int test_no_transport_params(void)
     if (!TEST_ptr(cctx))
         goto err;
 
-    if (!TEST_true(qtest_create_quic_objects(NULL, cctx, cert, privkey, 0,
+    if (!TEST_true(qtest_create_quic_objects(NULL, cctx, NULL, cert, privkey, 0,
                                              &qtserv, &cssl, &fault)))
         goto err;
 
@@ -263,7 +263,7 @@ static int test_corrupted_data(int idx)
     if (!TEST_ptr(cctx))
         goto err;
 
-    if (!TEST_true(qtest_create_quic_objects(NULL, cctx, cert, privkey,
+    if (!TEST_true(qtest_create_quic_objects(NULL, cctx, NULL, cert, privkey,
                                              QTEST_FLAG_FAKE_TIME, &qtserv,
                                              &cssl, &fault)))
         goto err;