Fix intermittent sslapitest early data related failures
[openssl.git] / test / quic_txp_test.c
index bd72a9b19a2bcf6affa66b4ce0a2b753b2a09ca5..f234fb683ac9199d4d3c449ae849a838d5357b62 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -108,6 +108,17 @@ static void helper_cleanup(struct helper *h)
     BIO_free(h->bio2);
 }
 
+static void demux_default_handler(QUIC_URXE *e, void *arg,
+                                  const QUIC_CONN_ID *dcid)
+{
+    struct helper *h = arg;
+
+    if (dcid == NULL || !ossl_quic_conn_id_eq(dcid, &dcid_1))
+        return;
+
+    ossl_qrx_inject_urxe(h->qrx, e);
+}
+
 static int helper_init(struct helper *h)
 {
     int rc = 0;
@@ -204,6 +215,8 @@ static int helper_init(struct helper *h)
                                                  fake_now, NULL)))
         goto err;
 
+    ossl_quic_demux_set_default_handler(h->demux, demux_default_handler, h);
+
     h->qrx_args.demux                  = h->demux;
     h->qrx_args.short_conn_id_len      = 8;
     h->qrx_args.max_deferred           = 32;
@@ -211,8 +224,7 @@ static int helper_init(struct helper *h)
     if (!TEST_ptr(h->qrx = ossl_qrx_new(&h->qrx_args)))
         goto err;
 
-    if (!TEST_true(ossl_qrx_add_dst_conn_id(h->qrx, &dcid_1)))
-        goto err;
+    ossl_qrx_allow_1rtt_processing(h->qrx);
 
     rc = 1;
 err:
@@ -245,6 +257,7 @@ err:
 #define OPK_CONN_TXFC_BUMP          20  /* Bump connection TXFC CWM */
 #define OPK_STREAM_TXFC_BUMP        21  /* Bump stream TXFC CWM */
 #define OPK_HANDSHAKE_COMPLETE      22  /* Mark handshake as complete */
+#define OPK_NOP                     23  /* No-op */
 
 struct script_op {
     uint32_t opcode;
@@ -300,6 +313,8 @@ struct script_op {
     { OPK_STREAM_TXFC_BUMP, (cwm), (id) },
 #define OP_HANDSHAKE_COMPLETE() \
     { OPK_HANDSHAKE_COMPLETE },
+#define OP_NOP() \
+    { OPK_NOP },
 
 static int schedule_handshake_done(struct helper *h)
 {
@@ -398,7 +413,7 @@ static int schedule_cfq_new_conn_id(struct helper *h)
     ncid.seq_num         = 2345;
     ncid.retire_prior_to = 1234;
     ncid.conn_id         = cid_1;
-    memcpy(ncid.stateless_reset_token, reset_token_1, sizeof(reset_token_1));
+    memcpy(ncid.stateless_reset.token, reset_token_1, sizeof(reset_token_1));
 
     if (!TEST_ptr(buf_mem = BUF_MEM_new()))
         goto err;
@@ -418,7 +433,7 @@ static int schedule_cfq_new_conn_id(struct helper *h)
 
     if (!TEST_ptr(cfq_item = ossl_quic_cfq_add_frame(h->args.cfq, 1,
                                                      QUIC_PN_SPACE_APP,
-                                                     OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID,
+                                                     OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID, 0,
                                                      (unsigned char *)buf_mem->data, l,
                                                      free_buf_mem,
                                                      buf_mem)))
@@ -437,7 +452,7 @@ static int check_cfq_new_conn_id(struct helper *h)
         || !TEST_uint64_t_eq(h->frame.new_conn_id.retire_prior_to, 1234)
         || !TEST_mem_eq(&h->frame.new_conn_id.conn_id, sizeof(cid_1),
                         &cid_1, sizeof(cid_1))
-        || !TEST_mem_eq(&h->frame.new_conn_id.stateless_reset_token,
+        || !TEST_mem_eq(&h->frame.new_conn_id.stateless_reset.token,
                         sizeof(reset_token_1),
                         reset_token_1,
                         sizeof(reset_token_1)))
@@ -494,7 +509,7 @@ static int schedule_cfq_new_token(struct helper *h)
 
     if (!TEST_ptr(cfq_item = ossl_quic_cfq_add_frame(h->args.cfq, 1,
                                                      QUIC_PN_SPACE_APP,
-                                                     OSSL_QUIC_FRAME_TYPE_NEW_TOKEN,
+                                                     OSSL_QUIC_FRAME_TYPE_NEW_TOKEN, 0,
                                                      (unsigned char *)buf_mem->data, l,
                                                      free_buf_mem,
                                                      buf_mem)))
@@ -1193,6 +1208,54 @@ static const struct script_op script_17[] = {
     OP_END
 };
 
+/* 18. Big Token Rejection */
+static const unsigned char big_token[1950];
+
+static int try_big_token(struct helper *h)
+{
+    size_t i;
+
+    /* Ensure big token is rejected */
+    if (!TEST_false(ossl_quic_tx_packetiser_set_initial_token(h->txp,
+                                                              big_token,
+                                                              sizeof(big_token),
+                                                              NULL,
+                                                              NULL)))
+        return 0;
+
+    /*
+     * Keep trying until we find an acceptable size, then make sure
+     * that works for generation
+     */
+    for (i = sizeof(big_token) - 1;; --i) {
+        if (!TEST_size_t_gt(i, 0))
+            return 0;
+
+        if (ossl_quic_tx_packetiser_set_initial_token(h->txp, big_token, i,
+                                                      NULL, NULL))
+            break;
+    }
+
+    return 1;
+}
+
+static const struct script_op script_18[] = {
+    OP_PROVIDE_SECRET(QUIC_ENC_LEVEL_INITIAL, QRL_SUITE_AES128GCM, secret_1)
+    OP_TXP_GENERATE_NONE()
+    OP_CHECK(try_big_token)
+    OP_TXP_GENERATE_NONE()
+    OP_CRYPTO_SEND(QUIC_PN_SPACE_INITIAL, crypto_1)
+    OP_TXP_GENERATE()
+    OP_RX_PKT()
+    OP_EXPECT_DGRAM_LEN(1200, 1200)
+    OP_NEXT_FRAME()
+    OP_EXPECT_FRAME(OSSL_QUIC_FRAME_TYPE_CRYPTO)
+    OP_EXPECT_NO_FRAME()
+    OP_RX_PKT_NONE()
+    OP_TXP_GENERATE_NONE()
+    OP_END
+};
+
 static const struct script_op *const scripts[] = {
     script_1,
     script_2,
@@ -1210,7 +1273,8 @@ static const struct script_op *const scripts[] = {
     script_14,
     script_15,
     script_16,
-    script_17
+    script_17,
+    script_18
 };
 
 static void skip_padding(struct helper *h)
@@ -1239,16 +1303,16 @@ static int run_script(int script_idx, const struct script_op *script)
     for (op = script, opn = 0; op->opcode != OPK_END; ++op, ++opn) {
         switch (op->opcode) {
         case OPK_TXP_GENERATE:
-            if (!TEST_int_eq(ossl_quic_tx_packetiser_generate(h.txp, &status),
-                             TX_PACKETISER_RES_SENT_PKT))
+            if (!TEST_true(ossl_quic_tx_packetiser_generate(h.txp, &status))
+                && !TEST_size_t_gt(status.sent_pkt, 0))
                 goto err;
 
             ossl_qtx_finish_dgram(h.args.qtx);
             ossl_qtx_flush_net(h.args.qtx);
             break;
         case OPK_TXP_GENERATE_NONE:
-            if (!TEST_int_eq(ossl_quic_tx_packetiser_generate(h.txp, &status),
-                             TX_PACKETISER_RES_NO_PKT))
+            if (!TEST_true(ossl_quic_tx_packetiser_generate(h.txp, &status))
+                && !TEST_size_t_eq(status.sent_pkt, 0))
                 goto err;
 
             break;
@@ -1526,6 +1590,8 @@ static int run_script(int script_idx, const struct script_op *script)
         case OPK_HANDSHAKE_COMPLETE:
             ossl_quic_tx_packetiser_notify_handshake_complete(h.txp);
             break;
+        case OPK_NOP:
+            break;
         default:
             TEST_error("bad opcode");
             goto err;
@@ -1543,7 +1609,6 @@ err:
 
 static int test_script(int idx)
 {
-    if (idx + 1 != 18) return 1;
     return run_script(idx, scripts[idx]);
 }
 
@@ -1574,6 +1639,16 @@ static int test_script(int idx)
 static const unsigned char dyn_script_1_crypto_1a[1200];
 static const unsigned char dyn_script_1_crypto_1b[1];
 
+static int check_is_initial(struct helper *h)
+{
+    return h->qrx_pkt->hdr->type == QUIC_PKT_TYPE_INITIAL;
+}
+
+static int check_is_handshake(struct helper *h)
+{
+    return h->qrx_pkt->hdr->type == QUIC_PKT_TYPE_HANDSHAKE;
+}
+
 static struct script_op dyn_script_1[] = {
     OP_PROVIDE_SECRET(QUIC_ENC_LEVEL_INITIAL, QRL_SUITE_AES128GCM, secret_1)
     OP_PROVIDE_SECRET(QUIC_ENC_LEVEL_HANDSHAKE, QRL_SUITE_AES128GCM, secret_1)
@@ -1583,18 +1658,33 @@ static struct script_op dyn_script_1[] = {
     OP_TXP_GENERATE()
     OP_RX_PKT()
     OP_EXPECT_DGRAM_LEN(1200, 1200)
+    OP_CHECK(check_is_initial)
+    OP_NOP() /* [pkt_idx] */
+    OP_NOP() /* [check_idx] */
     OP_END
 };
 
-static const size_t dyn_script_1_crypto_idx = 3;
-static const size_t dyn_script_1_start_from = 1000;
+static const size_t dyn_script_1_crypto_idx     = 3;
+static const size_t dyn_script_1_pkt_idx        = 9;
+static const size_t dyn_script_1_check_idx      = 10;
+static const size_t dyn_script_1_start_from     = 1000;
 
 static int test_dyn_script_1(int idx)
 {
     size_t target_size = dyn_script_1_start_from + (size_t)idx;
+    int expect_handshake_pkt_in_same_dgram = (target_size <= 1115);
 
     dyn_script_1[dyn_script_1_crypto_idx].buf_len = target_size;
 
+    if (expect_handshake_pkt_in_same_dgram) {
+        dyn_script_1[dyn_script_1_pkt_idx].opcode       = OPK_RX_PKT;
+        dyn_script_1[dyn_script_1_check_idx].opcode     = OPK_CHECK;
+        dyn_script_1[dyn_script_1_check_idx].check_func = check_is_handshake;
+    } else {
+        dyn_script_1[dyn_script_1_pkt_idx].opcode       = OPK_RX_PKT_NONE;
+        dyn_script_1[dyn_script_1_check_idx].opcode     = OPK_NOP;
+    }
+
     if (!run_script(idx, dyn_script_1)) {
         TEST_error("failed dyn script 1 with target size %zu", target_size);
         return 0;