mirror of
https://github.com/openssl/openssl.git
synced 2025-01-12 13:36:28 +08:00
QUIC: Echo PATH_CHALLENGE frames as PATH_RESPONSE frames
Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/21547)
This commit is contained in:
parent
7c729851d1
commit
7eb330ff7a
@ -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
|
||||
|
@ -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,
|
||||
@ -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,
|
||||
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -824,6 +824,7 @@ out:
|
||||
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) */
|
||||
{
|
||||
@ -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,
|
||||
@ -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,
|
||||
@ -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;
|
||||
|
@ -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 {
|
||||
@ -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,
|
||||
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user