/*
- * 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
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;
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;
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:
#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;
{ 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)
{
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;
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)))
|| !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)))
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)))
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,
script_14,
script_15,
script_16,
- script_17
+ script_17,
+ script_18
};
static void skip_padding(struct helper *h)
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;
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;
static int test_script(int idx)
{
- if (idx + 1 != 18) return 1;
return run_script(idx, scripts[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)
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;