diff --git a/src/transport/xqc_conn.c b/src/transport/xqc_conn.c index 8f7dc999d..95ef729b1 100644 --- a/src/transport/xqc_conn.c +++ b/src/transport/xqc_conn.c @@ -6500,6 +6500,16 @@ xqc_conn_set_early_remote_transport_params(xqc_connection_t *conn, } xqc_settings_copy_from_transport_params(&conn->remote_settings, params); + + /* + * RFC 9000 §7.4.1: a client MUST NOT use remembered values for + * max_ack_delay, ack_delay_exponent, or stateless_reset_token. + * Reset them to defaults so the 0-RTT path never relies on stale values. + */ + conn->remote_settings.max_ack_delay = XQC_DEFAULT_MAX_ACK_DELAY; + conn->remote_settings.ack_delay_exponent = XQC_DEFAULT_ACK_DELAY_EXPONENT; + conn->remote_settings.stateless_reset_token_present = 0; + xqc_conn_update_flow_ctl_settings(conn); return XQC_OK; } diff --git a/tests/unittest/main.c b/tests/unittest/main.c index ed5343150..8658f64b7 100644 --- a/tests/unittest/main.c +++ b/tests/unittest/main.c @@ -228,6 +228,8 @@ main() xqc_test_0rtt_params_all_increased) || !CU_add_test(pSuite, "xqc_test_0rtt_params_each_reduced", xqc_test_0rtt_params_each_reduced) + || !CU_add_test(pSuite, "xqc_test_early_params_forbidden_fields_reset", + xqc_test_early_params_forbidden_fields_reset) /* ALPN negotiation tests (issue #709) */ || !CU_add_test(pSuite, "xqc_test_alpn_error_code_value", xqc_test_alpn_error_code_value) diff --git a/tests/unittest/xqc_conn_test.c b/tests/unittest/xqc_conn_test.c index d7c05d9b3..5f7617215 100644 --- a/tests/unittest/xqc_conn_test.c +++ b/tests/unittest/xqc_conn_test.c @@ -635,6 +635,46 @@ xqc_test_0rtt_params_each_reduced(void) } +/* + * RFC 9000 §7.4.1: client MUST NOT use remembered values for max_ack_delay, + * ack_delay_exponent, or stateless_reset_token. Verify that + * xqc_conn_set_early_remote_transport_params resets them to defaults. + */ +void +xqc_test_early_params_forbidden_fields_reset(void) +{ + xqc_connection_t *conn = test_engine_connect(); + CU_ASSERT_FATAL(conn != NULL); + + xqc_transport_params_t params; + memset(¶ms, 0, sizeof(params)); + + /* set forbidden fields to non-default values */ + params.max_ack_delay = 100; /* default is 25 */ + params.ack_delay_exponent = 10; /* default is 3 */ + params.stateless_reset_token_present = 1; + memset(params.stateless_reset_token, 0xAB, sizeof(params.stateless_reset_token)); + + /* also set allowed fields */ + params.initial_max_data = 65536; + params.initial_max_streams_bidi = 100; + + xqc_int_t ret = xqc_conn_set_early_remote_transport_params(conn, ¶ms); + CU_ASSERT_EQUAL(ret, XQC_OK); + + /* forbidden fields must be reset to defaults */ + CU_ASSERT_EQUAL(conn->remote_settings.max_ack_delay, XQC_DEFAULT_MAX_ACK_DELAY); + CU_ASSERT_EQUAL(conn->remote_settings.ack_delay_exponent, XQC_DEFAULT_ACK_DELAY_EXPONENT); + CU_ASSERT_EQUAL(conn->remote_settings.stateless_reset_token_present, 0); + + /* allowed fields must be preserved */ + CU_ASSERT_EQUAL(conn->remote_settings.max_data, 65536); + CU_ASSERT_EQUAL(conn->remote_settings.max_streams_bidi, 100); + + xqc_engine_destroy(conn->engine); +} + + void xqc_test_conn_tls_error_cb_max_alert() { diff --git a/tests/unittest/xqc_conn_test.h b/tests/unittest/xqc_conn_test.h index 4330ffb2a..18ad4e1fb 100644 --- a/tests/unittest/xqc_conn_test.h +++ b/tests/unittest/xqc_conn_test.h @@ -22,6 +22,9 @@ void xqc_test_0rtt_params_all_equal(void); void xqc_test_0rtt_params_all_increased(void); void xqc_test_0rtt_params_each_reduced(void); +/* RFC 9000 §7.4.1: forbidden remembered fields must be reset (issue #672) */ +void xqc_test_early_params_forbidden_fields_reset(void); + /* ALPN negotiation tests (issue #709) */ void xqc_test_alpn_error_code_value(void); void xqc_test_alpn_server_cb_propagates_error(void);