Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
184 changes: 99 additions & 85 deletions src/transport/xqc_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -6069,6 +6069,94 @@ xqc_check_fec_trans_param(xqc_connection_t *conn, xqc_transport_params_t params)
}
}

/*
* RFC 9000 Section 7.4.1 and RFC 9221 Section 3: validate that new
* transport parameters do not reduce 0-RTT-sensitive parameters below the
* remembered values.
*
* Returns XQC_OK if all parameters are valid, or an error code
* (TRA_0RTT_TRANS_PARAMS_ERROR) if any MUST parameter was reduced.
*/
xqc_int_t
xqc_conn_validate_0rtt_transport_params(xqc_connection_t *conn,
const xqc_transport_params_t *params)
{
xqc_trans_settings_t *remembered = &conn->remote_settings;

if (params->initial_max_data < remembered->max_data) {
xqc_log(conn->log, XQC_LOG_ERROR,
"|0rtt_param_reduced|initial_max_data|"
"remembered:%ui|new:%ui|",
remembered->max_data, params->initial_max_data);
return TRA_0RTT_TRANS_PARAMS_ERROR;
}

if (params->initial_max_stream_data_bidi_local < remembered->max_stream_data_bidi_local) {
xqc_log(conn->log, XQC_LOG_ERROR,
"|0rtt_param_reduced|initial_max_stream_data_bidi_local|"
"remembered:%ui|new:%ui|",
remembered->max_stream_data_bidi_local,
params->initial_max_stream_data_bidi_local);
return TRA_0RTT_TRANS_PARAMS_ERROR;
}

if (params->initial_max_stream_data_bidi_remote < remembered->max_stream_data_bidi_remote) {
xqc_log(conn->log, XQC_LOG_ERROR,
"|0rtt_param_reduced|initial_max_stream_data_bidi_remote|"
"remembered:%ui|new:%ui|",
remembered->max_stream_data_bidi_remote,
params->initial_max_stream_data_bidi_remote);
return TRA_0RTT_TRANS_PARAMS_ERROR;
}

if (params->initial_max_stream_data_uni < remembered->max_stream_data_uni) {
xqc_log(conn->log, XQC_LOG_ERROR,
"|0rtt_param_reduced|initial_max_stream_data_uni|"
"remembered:%ui|new:%ui|",
remembered->max_stream_data_uni,
params->initial_max_stream_data_uni);
return TRA_0RTT_TRANS_PARAMS_ERROR;
}

if (params->initial_max_streams_bidi < remembered->max_streams_bidi) {
xqc_log(conn->log, XQC_LOG_ERROR,
"|0rtt_param_reduced|initial_max_streams_bidi|"
"remembered:%ui|new:%ui|",
remembered->max_streams_bidi,
params->initial_max_streams_bidi);
return TRA_0RTT_TRANS_PARAMS_ERROR;
}

if (params->initial_max_streams_uni < remembered->max_streams_uni) {
xqc_log(conn->log, XQC_LOG_ERROR,
"|0rtt_param_reduced|initial_max_streams_uni|"
"remembered:%ui|new:%ui|",
remembered->max_streams_uni,
params->initial_max_streams_uni);
return TRA_0RTT_TRANS_PARAMS_ERROR;
}

if (params->active_connection_id_limit < remembered->active_connection_id_limit) {
xqc_log(conn->log, XQC_LOG_ERROR,
"|0rtt_param_reduced|active_connection_id_limit|"
"remembered:%ui|new:%ui|",
remembered->active_connection_id_limit,
params->active_connection_id_limit);
return TRA_0RTT_TRANS_PARAMS_ERROR;
}

if (params->max_datagram_frame_size < remembered->max_datagram_frame_size) {
xqc_log(conn->log, XQC_LOG_ERROR,
"|0rtt_param_reduced|max_datagram_frame_size|"
"remembered:%ui|new:%ui|",
remembered->max_datagram_frame_size,
params->max_datagram_frame_size);
return TRA_0RTT_TRANS_PARAMS_ERROR;
}

return XQC_OK;
}

void
xqc_conn_tls_transport_params_cb(const uint8_t *tp, size_t len, void *user_data)
{
Expand Down Expand Up @@ -6100,8 +6188,8 @@ xqc_conn_tls_transport_params_cb(const uint8_t *tp, size_t len, void *user_data)
}

/*
* RFC 9000 Section 7.4.1: when a client has sent 0-RTT data AND the
* server accepted early data, the server MUST NOT reduce certain
* RFC 9000 Section 7.4.1: when a client has sent 0-RTT data and the
* server accepted early data, the server MUST NOT reduce the core
* transport parameters below the remembered values. The client MUST
* validate this and close with TRANSPORT_PARAMETER_ERROR if any MUST
* parameter was reduced.
Expand All @@ -6117,93 +6205,19 @@ xqc_conn_tls_transport_params_cb(const uint8_t *tp, size_t len, void *user_data)
&& (conn->conn_flag & XQC_CONN_FLAG_HAS_0RTT)
&& xqc_tls_is_early_data_accepted(conn->tls) == XQC_TLS_EARLY_DATA_ACCEPT)
{
xqc_trans_settings_t *remembered = &conn->remote_settings;

/*
* MUST parameters -- server MUST NOT reduce these after 0-RTT is
* accepted (RFC 9000 Section 7.4.1):
* - active_connection_id_limit
* - initial_max_data
* - initial_max_stream_data_bidi_local
* - initial_max_stream_data_bidi_remote
* - initial_max_stream_data_uni
* - initial_max_streams_bidi
* - initial_max_streams_uni
*/
if (params.initial_max_data < remembered->max_data) {
xqc_log(conn->log, XQC_LOG_ERROR,
"|0rtt_param_reduced|initial_max_data|"
"remembered:%ui|new:%ui|",
remembered->max_data, params.initial_max_data);
XQC_CONN_ERR(conn, TRA_0RTT_TRANS_PARAMS_ERROR);
return;
}

if (params.initial_max_stream_data_bidi_local < remembered->max_stream_data_bidi_local) {
xqc_log(conn->log, XQC_LOG_ERROR,
"|0rtt_param_reduced|initial_max_stream_data_bidi_local|"
"remembered:%ui|new:%ui|",
remembered->max_stream_data_bidi_local,
params.initial_max_stream_data_bidi_local);
XQC_CONN_ERR(conn, TRA_0RTT_TRANS_PARAMS_ERROR);
return;
}

if (params.initial_max_stream_data_bidi_remote < remembered->max_stream_data_bidi_remote) {
xqc_log(conn->log, XQC_LOG_ERROR,
"|0rtt_param_reduced|initial_max_stream_data_bidi_remote|"
"remembered:%ui|new:%ui|",
remembered->max_stream_data_bidi_remote,
params.initial_max_stream_data_bidi_remote);
XQC_CONN_ERR(conn, TRA_0RTT_TRANS_PARAMS_ERROR);
return;
}

if (params.initial_max_stream_data_uni < remembered->max_stream_data_uni) {
xqc_log(conn->log, XQC_LOG_ERROR,
"|0rtt_param_reduced|initial_max_stream_data_uni|"
"remembered:%ui|new:%ui|",
remembered->max_stream_data_uni,
params.initial_max_stream_data_uni);
XQC_CONN_ERR(conn, TRA_0RTT_TRANS_PARAMS_ERROR);
return;
}

if (params.initial_max_streams_bidi < remembered->max_streams_bidi) {
xqc_log(conn->log, XQC_LOG_ERROR,
"|0rtt_param_reduced|initial_max_streams_bidi|"
"remembered:%ui|new:%ui|",
remembered->max_streams_bidi,
params.initial_max_streams_bidi);
XQC_CONN_ERR(conn, TRA_0RTT_TRANS_PARAMS_ERROR);
return;
}

if (params.initial_max_streams_uni < remembered->max_streams_uni) {
xqc_log(conn->log, XQC_LOG_ERROR,
"|0rtt_param_reduced|initial_max_streams_uni|"
"remembered:%ui|new:%ui|",
remembered->max_streams_uni,
params.initial_max_streams_uni);
XQC_CONN_ERR(conn, TRA_0RTT_TRANS_PARAMS_ERROR);
return;
}

if (params.active_connection_id_limit < remembered->active_connection_id_limit) {
xqc_log(conn->log, XQC_LOG_ERROR,
"|0rtt_param_reduced|active_connection_id_limit|"
"remembered:%ui|new:%ui|",
remembered->active_connection_id_limit,
params.active_connection_id_limit);
XQC_CONN_ERR(conn, TRA_0RTT_TRANS_PARAMS_ERROR);
ret = xqc_conn_validate_0rtt_transport_params(conn, &params);
if (ret != XQC_OK) {
XQC_CONN_ERR(conn, ret);
return;
}

}

/* check datagram parameter -- unconditional, not gated on early_data
* accepted. For non-0RTT connections remote_settings.max_datagram_frame_size
* is 0, so this is a no-op. */
/*
* RFC 9221 Section 3: if max_datagram_frame_size is remembered as 0-RTT
* state, the new value MUST NOT be smaller. This check is not gated on
* the TLS early-data result; for non-0RTT connections the remembered value
* is zero, so it remains a no-op.
*/
if (params.max_datagram_frame_size < conn->remote_settings.max_datagram_frame_size) {
xqc_log(conn->log, XQC_LOG_ERROR,
"|0rtt_param_reduced|max_datagram_frame_size|"
Expand Down
11 changes: 11 additions & 0 deletions src/transport/xqc_conn.h
Original file line number Diff line number Diff line change
Expand Up @@ -749,4 +749,15 @@ void xqc_conn_set_init_idle_timeout(xqc_connection_t *conn, xqc_msec_t init_idle
void xqc_conn_try_to_enable_pmtud(xqc_connection_t *conn);

xqc_int_t xqc_conn_server_accept(xqc_connection_t *c);

/*
* RFC 9000 Section 7.4.1 and RFC 9221 Section 3: validate that new transport
* parameters do not reduce 0-RTT-sensitive parameters below remembered values.
*
* Returns XQC_OK if all parameters are valid, or TRA_0RTT_TRANS_PARAMS_ERROR
* if any MUST parameter was reduced.
*/
xqc_int_t xqc_conn_validate_0rtt_transport_params(xqc_connection_t *conn,
const xqc_transport_params_t *params);

#endif /* _XQC_CONN_H_INCLUDED_ */
15 changes: 8 additions & 7 deletions tests/unittest/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,14 @@ main()
|| !CU_add_test(pSuite, "xqc_test_crypto_frame_dispatched_via_xqc_process_frame", xqc_test_crypto_frame_dispatched_via_xqc_process_frame)
|| !CU_add_test(pSuite, "xqc_test_crypto_in_0rtt_emits_connection_close", xqc_test_crypto_in_0rtt_emits_connection_close)
|| !CU_add_test(pSuite, "xqc_test_crypto", xqc_test_crypto)
/* issue #717: 0-RTT transport parameter validation (RFC 9000 Section 7.4.1)
* registered before hp_sample_boundary to avoid a pre-existing SIGSEGV */
|| !CU_add_test(pSuite, "xqc_test_0rtt_params_all_equal",
xqc_test_0rtt_params_all_equal)
|| !CU_add_test(pSuite, "xqc_test_0rtt_params_all_increased",
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_hp_sample_boundary", xqc_test_hp_sample_boundary)
|| !CU_add_test(pSuite, "xqc_test_packet_encrypt_hp_sample_boundary", xqc_test_packet_encrypt_hp_sample_boundary)
|| !CU_add_test(pSuite, "xqc_test_empty_pkt", xqc_test_empty_pkt)
Expand Down Expand Up @@ -221,13 +229,6 @@ main()
|| !CU_add_test(pSuite, "xqc_test_initial_salt_length", xqc_test_initial_salt_length)
|| !CU_add_test(pSuite, "xqc_test_initial_salt_v1_value", xqc_test_initial_salt_v1_value)
|| !CU_add_test(pSuite, "xqc_test_initial_salt_null_byte_regression", xqc_test_initial_salt_null_byte_regression)
/* issue #717: 0-RTT transport parameter validation (RFC 9000 Section 7.4.1) */
|| !CU_add_test(pSuite, "xqc_test_0rtt_params_all_equal",
xqc_test_0rtt_params_all_equal)
|| !CU_add_test(pSuite, "xqc_test_0rtt_params_all_increased",
xqc_test_0rtt_params_all_increased)
|| !CU_add_test(pSuite, "xqc_test_0rtt_params_each_reduced",
xqc_test_0rtt_params_each_reduced)
/* ALPN negotiation tests (issue #709) */
|| !CU_add_test(pSuite, "xqc_test_alpn_error_code_value",
xqc_test_alpn_error_code_value)
Expand Down
Loading
Loading