Skip to content

Commit

Permalink
QUIC: Echo PATH_CHALLENGE frames as PATH_RESPONSE frames
Browse files Browse the repository at this point in the history
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from #21547)
  • Loading branch information
hlandau authored and mattcaswell committed Aug 8, 2023
1 parent 7c72985 commit 7eb330f
Show file tree
Hide file tree
Showing 5 changed files with 186 additions and 3 deletions.
8 changes: 8 additions & 0 deletions include/internal/quic_tserver.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,14 @@ int ossl_quic_tserver_shutdown(QUIC_TSERVER *srv);
/* Force generation of an ACK-eliciting packet. */
int ossl_quic_tserver_ping(QUIC_TSERVER *srv);

/* Set tracing callback on channel. */
void ossl_quic_tserver_set_msg_callback(QUIC_TSERVER *srv,
void (*f)(int write_p, int version,
int content_type,
const void *buf, size_t len,
SSL *ssl, void *arg),
void *arg);

# endif

#endif
43 changes: 42 additions & 1 deletion ssl/quic/quic_rx_depack.c
Original file line number Diff line number Diff line change
Expand Up @@ -875,11 +875,19 @@ static int depack_do_frame_retire_conn_id(PACKET *pkt,
return 1;
}

static void free_path_response(unsigned char *buf, size_t buf_len, void *arg)
{
OPENSSL_free(buf);
}

static int depack_do_frame_path_challenge(PACKET *pkt,
QUIC_CHANNEL *ch,
OSSL_ACKM_RX_PKT *ackm_data)
{
uint64_t frame_data = 0;
unsigned char *encoded = NULL;
size_t encoded_len;
WPACKET wpkt;

if (!ossl_quic_wire_decode_frame_path_challenge(pkt, &frame_data)) {
ossl_quic_channel_raise_protocol_error(ch,
Expand All @@ -889,9 +897,41 @@ static int depack_do_frame_path_challenge(PACKET *pkt,
return 0;
}

/* TODO(QUIC): ADD CODE to send |frame_data| to the ch manager */
/*
* RFC 9000 s. 8.2.2: On receiving a PATH_CHALLENGE frame, an endpoint MUST
* respond by echoing the data contained in the PATH_CHALLENGE frame in a
* PATH_RESPONSE frame.
*
* TODO(QUIC): We should try to avoid allocation here in the future.
*/
encoded_len = sizeof(uint64_t) + 1;
if ((encoded = OPENSSL_malloc(encoded_len)) == NULL)
goto err;

if (!WPACKET_init_static_len(&wpkt, encoded, encoded_len, 0))
goto err;

if (!ossl_quic_wire_encode_frame_path_response(&wpkt, frame_data)) {
WPACKET_cleanup(&wpkt);
goto err;
}

WPACKET_finish(&wpkt);

if (!ossl_quic_cfq_add_frame(ch->cfq, 0, QUIC_PN_SPACE_APP,
OSSL_QUIC_FRAME_TYPE_PATH_RESPONSE,
encoded, encoded_len,
free_path_response, NULL))
goto err;

return 1;

err:
OPENSSL_free(encoded);
ossl_quic_channel_raise_protocol_error(ch, QUIC_ERR_INTERNAL_ERROR,
OSSL_QUIC_FRAME_TYPE_PATH_CHALLENGE,
"internal error");
return 0;
}

static int depack_do_frame_path_response(PACKET *pkt,
Expand Down Expand Up @@ -1224,6 +1264,7 @@ static int depack_process_frames(QUIC_CHANNEL *ch, PACKET *pkt,
}
if (!depack_do_frame_path_challenge(pkt, ch, ackm_data))
return 0;

break;
case OSSL_QUIC_FRAME_TYPE_PATH_RESPONSE:
/* PATH_RESPONSE frames are valid in 1RTT packets */
Expand Down
11 changes: 11 additions & 0 deletions ssl/quic/quic_tserver.c
Original file line number Diff line number Diff line change
Expand Up @@ -511,3 +511,14 @@ int ossl_quic_tserver_ping(QUIC_TSERVER *srv)
ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(srv->ch), 0);
return 1;
}

void ossl_quic_tserver_set_msg_callback(QUIC_TSERVER *srv,
void (*f)(int write_p, int version,
int content_type,
const void *buf, size_t len,
SSL *ssl, void *arg),
void *arg)
{
ossl_quic_channel_set_msg_callback(srv->ch, f, NULL);
ossl_quic_channel_set_msg_callback_arg(srv->ch, arg);
}
9 changes: 7 additions & 2 deletions ssl/quic/quic_txp.c
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,7 @@ int ossl_quic_tx_packetiser_generate(OSSL_QUIC_TX_PACKETISER *txp,
return pkts_done > 0 ? TX_PACKETISER_RES_SENT_PKT : res;
}


static const struct archetype_data archetypes[QUIC_ENC_LEVEL_NUM][TX_PACKETISER_ARCHETYPE_NUM] = {
/* EL 0(INITIAL) */
{
Expand Down Expand Up @@ -1023,7 +1024,7 @@ static const struct archetype_data archetypes[QUIC_ENC_LEVEL_NUM][TX_PACKETISER_
/*allow_crypto =*/ 1,
/*allow_handshake_done =*/ 1,
/*allow_path_challenge =*/ 0,
/*allow_path_response =*/ 0,
/*allow_path_response =*/ 1,
/*allow_new_conn_id =*/ 1,
/*allow_retire_conn_id =*/ 1,
/*allow_stream_rel =*/ 1,
Expand All @@ -1043,7 +1044,7 @@ static const struct archetype_data archetypes[QUIC_ENC_LEVEL_NUM][TX_PACKETISER_
/*allow_crypto =*/ 1,
/*allow_handshake_done =*/ 1,
/*allow_path_challenge =*/ 0,
/*allow_path_response =*/ 0,
/*allow_path_response =*/ 1,
/*allow_new_conn_id =*/ 1,
/*allow_retire_conn_id =*/ 1,
/*allow_stream_rel =*/ 1,
Expand Down Expand Up @@ -1339,6 +1340,10 @@ static int txp_should_try_staging(OSSL_QUIC_TX_PACKETISER *txp,
if (a.allow_new_token)
return 1;
break;
case OSSL_QUIC_FRAME_TYPE_PATH_RESPONSE:
if (a.allow_path_response)
return 1;
break;
default:
if (a.allow_cfq_other)
return 1;
Expand Down
118 changes: 118 additions & 0 deletions test/quic_multistream_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ struct helper {
int (*qtf_packet_plain_cb)(struct helper *h, QUIC_PKT_HDR *hdr,
unsigned char *buf, size_t buf_len);
uint64_t inject_word0, inject_word1;
uint64_t scratch0, scratch1;
};

struct helper_local {
Expand Down Expand Up @@ -2909,6 +2910,122 @@ static const struct script_op script_40[] = {
OP_END
};

/* 41. Fault injection - PATH_CHALLENGE yields PATH_RESPONSE */
static const uint64_t path_challenge = UINT64_C(0xbdeb9451169c83aa);

static int script_41_inject_plain(struct helper *h, QUIC_PKT_HDR *hdr,
unsigned char *buf, size_t len)
{
int ok = 0;
WPACKET wpkt;
unsigned char frame_buf[16];
size_t written;

if (h->inject_word0 == 0)
return 1;

if (!TEST_true(WPACKET_init_static_len(&wpkt, frame_buf,
sizeof(frame_buf), 0)))
return 0;

if (!TEST_true(WPACKET_quic_write_vlint(&wpkt, OSSL_QUIC_FRAME_TYPE_PATH_CHALLENGE))
|| !TEST_true(WPACKET_put_bytes_u64(&wpkt, path_challenge)))
goto err;

if (!TEST_true(WPACKET_get_total_written(&wpkt, &written))
|| !TEST_size_t_eq(written, 9))
goto err;

if (!qtest_fault_prepend_frame(h->qtf, frame_buf, written))
goto err;

--h->inject_word0;
ok = 1;
err:
if (ok)
WPACKET_finish(&wpkt);
else
WPACKET_cleanup(&wpkt);
return ok;
}

static void script_41_trace(int write_p, int version, int content_type,
const void *buf, size_t len, SSL *ssl, void *arg)
{
uint64_t frame_type, frame_data;
int was_minimal;
struct helper *h = arg;
PACKET pkt;

if (version != OSSL_QUIC1_VERSION
|| content_type != SSL3_RT_QUIC_FRAME_FULL
|| len < 1)
return;

if (!TEST_true(PACKET_buf_init(&pkt, buf, len))) {
++h->scratch1;
return;
}

if (!TEST_true(ossl_quic_wire_peek_frame_header(&pkt, &frame_type,
&was_minimal))) {
++h->scratch1;
return;
}

if (frame_type != OSSL_QUIC_FRAME_TYPE_PATH_RESPONSE)
return;

if (!TEST_true(ossl_quic_wire_decode_frame_path_response(&pkt, &frame_data))
|| !TEST_uint64_t_eq(frame_data, path_challenge)) {
++h->scratch1;
return;
}

++h->scratch0;
}

static int script_41_setup(struct helper *h, const struct script_op *op)
{
ossl_quic_tserver_set_msg_callback(h->s, script_41_trace, h);
return 1;
}

static int script_41_check(struct helper *h, const struct script_op *op)
{
/* At least one valid challenge/response echo? */
if (!TEST_uint64_t_gt(h->scratch0, 0))
return 0;

/* No failed tests? */
if (!TEST_uint64_t_eq(h->scratch1, 0))
return 0;

return 1;
}

static const struct script_op script_41[] = {
OP_S_SET_INJECT_PLAIN (script_41_inject_plain)
OP_C_SET_ALPN ("ossltest")
OP_C_CONNECT_WAIT ()
OP_CHECK (script_41_setup, 0)

OP_C_WRITE (DEFAULT, "apple", 5)
OP_S_BIND_STREAM_ID (a, C_BIDI_ID(0))
OP_S_READ_EXPECT (a, "apple", 5)

OP_SET_INJECT_WORD (1, 0)

OP_S_WRITE (a, "orange", 6)
OP_C_READ_EXPECT (DEFAULT, "orange", 6)

OP_C_WRITE (DEFAULT, "strawberry", 10)
OP_S_READ_EXPECT (a, "strawberry", 10)

OP_CHECK (script_41_check, 0)
OP_END
};

static const struct script_op *const scripts[] = {
script_1,
script_2,
Expand Down Expand Up @@ -2950,6 +3067,7 @@ static const struct script_op *const scripts[] = {
script_38,
script_39,
script_40,
script_41,
};

static int test_script(int idx)
Expand Down

0 comments on commit 7eb330f

Please sign in to comment.