Skip to content

Commit 9ccded0

Browse files
authored
[~]: Discard client-received 0-RTT packets (#870)
1 parent e7fe943 commit 9ccded0

4 files changed

Lines changed: 73 additions & 1 deletion

File tree

src/transport/xqc_packet.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,17 @@ xqc_packet_parse_single(xqc_connection_t *c, xqc_packet_in_t *packet_in)
155155
} else if (XQC_PACKET_IS_LONG_HEADER(pos)) { /* long header */
156156
/* buffer packets if key is not ready */
157157
if (XQC_PACKET_LONG_HEADER_GET_TYPE(packet_in->pos) == XQC_PTYPE_0RTT) {
158+
/*
159+
* RFC 9001 Section 5.6: a client MUST NOT attempt to decrypt a
160+
* received 0-RTT packet and MUST discard it.
161+
*/
162+
if (c->conn_type == XQC_CONN_TYPE_CLIENT) {
163+
xqc_log(c->log, XQC_LOG_INFO,
164+
"|discard 0-RTT packet received by client|"
165+
"RFC 9001 5.6|");
166+
return -XQC_EIGNORE_PKT;
167+
}
168+
158169
c->conn_flag |= XQC_CONN_FLAG_HAS_0RTT;
159170

160171
if (!xqc_tls_is_key_ready(c->tls, XQC_ENC_LEV_0RTT, XQC_KEY_TYPE_RX_READ)) {
@@ -283,4 +294,3 @@ xqc_packet_process_single(xqc_connection_t *c,
283294

284295

285296

286-

tests/unittest/main.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ main(int argc, char *argv[])
100100
|| !CU_add_test(pSuite, "xqc_test_cubic_init_cwnd", xqc_test_cubic_init_cwnd)
101101
|| !CU_add_test(pSuite, "xqc_test_short_header_parse_cid", xqc_test_short_header_packet_parse_cid)
102102
|| !CU_add_test(pSuite, "xqc_test_long_header_parse_cid", xqc_test_long_header_packet_parse_cid)
103+
|| !CU_add_test(pSuite, "xqc_test_client_discards_received_zero_rtt",
104+
xqc_test_client_discards_received_zero_rtt)
105+
|| !CU_add_test(pSuite, "xqc_test_server_buffers_received_zero_rtt",
106+
xqc_test_server_buffers_received_zero_rtt)
103107
|| !CU_add_test(pSuite, "xqc_test_crypto_frame_flood", xqc_test_crypto_frame_flood)
104108
|| !CU_add_test(pSuite, "xqc_test_crypto_frame_bytes_limit", xqc_test_crypto_frame_bytes_limit)
105109
|| !CU_add_test(pSuite, "xqc_test_crypto_frame_recycle", xqc_test_crypto_frame_recycle)

tests/unittest/xqc_packet_test.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919

2020
#define XQC_TEST_SHORT_HEADER_PACKET_A "\x40\xAB\x3f\x12\x0a\xcd\xef\x00\x89"
2121
#define XQC_TEST_LONG_HEADER_PACKET_B "\xC0\x00\x00\x00\x01\x08\xAB\x3f\x12\x0a\xcd\xef\x00\x89\x08\xAB\x3f\x12\x0a\xcd\xef\x00\x89"
22+
#define XQC_TEST_ZERO_RTT_PACKET \
23+
"\xD0\x00\x00\x00\x01\x08\xAB\x3f\x12\x0a\xcd\xef\x00\x89" \
24+
"\x08\xAB\x3f\x12\x0a\xcd\xef\x00\x89\x01\x00"
2225

2326
#define XQC_TEST_CHECK_CID "ab3f120acdef0089"
2427

@@ -67,6 +70,59 @@ xqc_test_long_header_packet_parse_cid()
6770
}
6871

6972

73+
void
74+
xqc_test_client_discards_received_zero_rtt(void)
75+
{
76+
xqc_connection_t *conn = test_engine_connect();
77+
xqc_packet_in_t packet_in;
78+
xqc_int_t ret;
79+
80+
CU_ASSERT_PTR_NOT_NULL_FATAL(conn);
81+
CU_ASSERT_EQUAL_FATAL(conn->conn_type, XQC_CONN_TYPE_CLIENT);
82+
83+
xqc_packet_in_init(&packet_in,
84+
(unsigned char *)XQC_TEST_ZERO_RTT_PACKET,
85+
sizeof(XQC_TEST_ZERO_RTT_PACKET) - 1, NULL, 0, 0);
86+
87+
ret = xqc_packet_process_single(conn, &packet_in);
88+
89+
/*
90+
* RFC 9001 Section 5.6 requires discard before decryption. The receive
91+
* path must not retain the packet or mark client-side 0-RTT state.
92+
*/
93+
CU_ASSERT_EQUAL(ret, -XQC_EIGNORE_PKT);
94+
CU_ASSERT_EQUAL(conn->undecrypt_count[XQC_ENC_LEV_0RTT], 0);
95+
CU_ASSERT_FALSE(conn->conn_flag & XQC_CONN_FLAG_HAS_0RTT);
96+
97+
xqc_engine_destroy(conn->engine);
98+
}
99+
100+
101+
void
102+
xqc_test_server_buffers_received_zero_rtt(void)
103+
{
104+
xqc_connection_t *conn = test_engine_connect();
105+
xqc_packet_in_t packet_in;
106+
xqc_int_t ret;
107+
108+
CU_ASSERT_PTR_NOT_NULL_FATAL(conn);
109+
conn->conn_type = XQC_CONN_TYPE_SERVER;
110+
111+
xqc_packet_in_init(&packet_in,
112+
(unsigned char *)XQC_TEST_ZERO_RTT_PACKET,
113+
sizeof(XQC_TEST_ZERO_RTT_PACKET) - 1, NULL, 0, 0);
114+
115+
ret = xqc_packet_process_single(conn, &packet_in);
116+
117+
CU_ASSERT_EQUAL(ret, -XQC_EWAITING);
118+
CU_ASSERT_EQUAL(conn->undecrypt_count[XQC_ENC_LEV_0RTT], 1);
119+
CU_ASSERT_TRUE(conn->conn_flag & XQC_CONN_FLAG_HAS_0RTT);
120+
121+
conn->conn_type = XQC_CONN_TYPE_CLIENT;
122+
xqc_engine_destroy(conn->engine);
123+
}
124+
125+
70126

71127

72128

tests/unittest/xqc_packet_test.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
void xqc_test_short_header_packet_parse_cid();
99
void xqc_test_long_header_packet_parse_cid();
10+
void xqc_test_client_discards_received_zero_rtt(void);
11+
void xqc_test_server_buffers_received_zero_rtt(void);
1012
void xqc_test_packet_encrypt_hp_sample_boundary();
1113
void xqc_test_empty_pkt();
1214
void xqc_test_stateless_reset_parse_boundary(void);

0 commit comments

Comments
 (0)