]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Add test to confirm new token functionality
authorNeil Horman <nhorman@openssl.org>
Tue, 21 Jan 2025 16:48:51 +0000 (11:48 -0500)
committerNeil Horman <nhorman@openssl.org>
Mon, 17 Feb 2025 16:27:33 +0000 (11:27 -0500)
Basically just create two clients and two servers, ensuring that both
clients use the same ctx (to share the token cache).

Connect the first client and server so that the cache gets populated
with a new token, tracing the ssl connection

Connect the second client and server, again tracing the connection with
the same bio

Then sift through the trace, looking for the new token frame in the
first connection, matching it with the token used in the second
connection.

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Saša Nedvědický <sashan@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26517)

test/quicapitest.c

index 504256ec73e053689705d715c3e23abaac910c9a..530a736eed875ec181948888384f8babc434c1a4 100644 (file)
@@ -554,6 +554,140 @@ static int test_ssl_trace(void)
 }
 #endif
 
+enum {
+    INITIAL = 0,
+    GATHER_TOKEN = 1,
+    CHECK_TOKEN = 2,
+    SUCCESS = 3,
+    FAILED = 4
+};
+
+static int find_new_token_data(BIO *membio)
+{
+    char buf[1024];
+    int state = INITIAL;
+    char *tmpstring;
+    char *tokenval = NULL;
+    /*
+     * This is a state machine, in which we traverse the ssl trace
+     * looking for a sequence of items
+     * The states are:
+     * +---Current State---|----------Action-------------|---Next State---+
+     * |      INITIAL      | "Received Frame: New token" | GATHER_TOKEN   |
+     * |                   | !"Received Frame: New token"| INITIAL        |
+     * |-------------------|-----------------------------|----------------|
+     * |    GATHER_TOKEN   | "Token: <TOKENVAL>"         | CHECK_TOKEN    |
+     * |                   | !"Token: <TOKENVAL>"        | FAILED         |
+     * |-------------------|-----------------------------|----------------|
+     * |    CHECK_TOKEN    | "Token: <TOKENVAL>"         | SUCCESS        |
+     * |                   | EOF                         | FAILED         |
+     * +-------------------|-----------------------------|----------------|
+     */
+
+    while (state != SUCCESS
+           && state != FAILED
+           && BIO_gets(membio, buf, sizeof(buf)) > 0) {
+        switch (state) {
+        case INITIAL:
+            if (strstr(buf, "Received Frame: New token"))
+                state = GATHER_TOKEN;
+            break;
+        case GATHER_TOKEN:
+            TEST_info("Found New Token Marker\n");
+            tmpstring = strstr(buf, "Token: ");
+            if (tmpstring == NULL) {
+                TEST_info("Next line did not contain a new token\n");
+                state = FAILED;
+            } else {
+                tokenval = strdup(tmpstring);
+                state = CHECK_TOKEN;
+                TEST_info("Recorded Token %s\n", tokenval);
+            }
+            break;
+        case CHECK_TOKEN:
+            tmpstring = strstr(buf, "Token: ");
+            if (tmpstring != NULL
+                && !strcmp(tmpstring, tokenval)) {
+                state = SUCCESS;
+                TEST_info("Matched next connection token %s\n", tmpstring);
+            }
+        default:
+            break;
+        }
+    }
+
+    OPENSSL_free(tokenval);
+    return (state == SUCCESS);
+}
+
+static int test_new_token(void)
+{
+    SSL_CTX *cctx = NULL;
+    SSL *clientquic = NULL;
+    SSL *clientquic2 = NULL;
+    QUIC_TSERVER *qtserv = NULL;
+    QUIC_TSERVER *qtserv2 = NULL;
+    int testresult = 0;
+    BIO *bio = NULL;
+    char msg[] = "The Quic Brown Fox";
+    size_t written;
+
+    if (!TEST_ptr(cctx = SSL_CTX_new_ex(libctx, NULL, OSSL_QUIC_client_method()))
+        || !TEST_ptr(bio = BIO_new(BIO_s_mem()))
+        || !TEST_true(qtest_create_quic_objects(libctx, cctx, NULL, cert,
+                                                privkey,
+                                                QTEST_FLAG_FAKE_TIME,
+                                                &qtserv,
+                                                &clientquic, NULL, NULL)))
+
+        goto err;
+
+    SSL_set_msg_callback(clientquic, SSL_trace);
+    SSL_set_msg_callback_arg(clientquic, bio);
+
+    if (!TEST_true(qtest_create_quic_connection(qtserv, clientquic)))
+        goto err;
+
+    /* Send data from the client */
+    if (!SSL_write_ex(clientquic, msg, sizeof(msg), &written))
+        goto err;
+
+    if (written != sizeof(msg))
+        goto err;
+
+    /* Receive data at the server */
+    ossl_quic_tserver_tick(qtserv);
+
+    if (!TEST_true(qtest_create_quic_objects(libctx, cctx, NULL, cert,
+                                             privkey,
+                                             QTEST_FLAG_FAKE_TIME,
+                                             &qtserv2,
+                                             &clientquic2, NULL, NULL)))
+        goto err;
+
+    SSL_set_msg_callback(clientquic2, SSL_trace);
+    SSL_set_msg_callback_arg(clientquic2, bio);
+
+    /* once we have our new token, create the subsequent connection */
+    if (!TEST_true(qtest_create_quic_connection(qtserv2, clientquic2)))
+        goto err;
+
+    /* Skip the comparison of the trace when the fips provider is used. */
+    if (!TEST_true(find_new_token_data(bio)))
+        goto err;
+
+    testresult = 1;
+ err:
+    ossl_quic_tserver_free(qtserv);
+    ossl_quic_tserver_free(qtserv2);
+    SSL_free(clientquic);
+    SSL_free(clientquic2);
+    SSL_CTX_free(cctx);
+    BIO_free(bio);
+
+    return testresult;
+}
+
 static int ensure_valid_ciphers(const STACK_OF(SSL_CIPHER) *ciphers)
 {
     size_t i;
@@ -2606,6 +2740,7 @@ int setup_tests(void)
     ADD_TEST(test_domain_flags);
     ADD_TEST(test_early_ticks);
     ADD_TEST(test_ssl_new_from_listener);
+    ADD_TEST(test_new_token);
     return 1;
  err:
     cleanup_tests();