From 29e861a5a6056aebe21af7d75d97caf2a8eff081 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Thu, 16 Jan 2025 15:34:33 -0500 Subject: [PATCH] Add lookup for initial token assignment on channel start MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Start assiging initial tokens, and validating them on receipt Reviewed-by: Matt Caswell Reviewed-by: Saša Nedvědický (Merged from https://github.com/openssl/openssl/pull/26517) --- ssl/quic/quic_channel.c | 33 ++++++++++++++++++++++++++++----- ssl/quic/quic_port.c | 19 +++++++++++++++++-- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index 3c13437bb54..a9b453e69f2 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -18,6 +18,7 @@ #include "internal/qlog_event_helpers.h" #include "internal/quic_txp.h" #include "internal/quic_tls.h" +#include "internal/quic_ssl.h" #include "../ssl_local.h" #include "quic_channel_local.h" #include "quic_port_local.h" @@ -2778,8 +2779,18 @@ static void ch_record_state_transition(QUIC_CHANNEL *ch, uint32_t new_state) ch->handshake_confirmed); } +static void free_peer_token(const unsigned char *token, + size_t token_len, void *arg) +{ + ossl_quic_free_peer_token((QTOK *)arg); +} + int ossl_quic_channel_start(QUIC_CHANNEL *ch) { + uint8_t *token; + size_t token_len; + void *token_ptr; + if (ch->is_server) /* * This is not used by the server. The server moves to active @@ -2795,6 +2806,18 @@ int ossl_quic_channel_start(QUIC_CHANNEL *ch) if (!ossl_quic_tx_packetiser_set_peer(ch->txp, &ch->cur_peer_addr)) return 0; + /* + * Look to see if we have a token, and if so, set it on the packetiser + */ + if (!ch->is_server && ossl_quic_get_peer_token(ch->port->channel_ctx, + &ch->cur_peer_addr, + &token, &token_len, + &token_ptr)) { + if (!ossl_quic_tx_packetiser_set_initial_token(ch->txp, token, + token_len, free_token, + token_ptr)) + free_token(NULL, 0, token_ptr); + } /* Plug in secrets for the Initial EL. */ if (!ossl_quic_provide_initial_secret(ch->port->engine->libctx, ch->port->engine->propq, @@ -2827,6 +2850,11 @@ int ossl_quic_channel_start(QUIC_CHANNEL *ch) return 1; } +static void free_token(const unsigned char *token, size_t token_len, void *arg) +{ + OPENSSL_free((char *)token); +} + /* Start a locally initiated connection shutdown. */ void ossl_quic_channel_local_close(QUIC_CHANNEL *ch, uint64_t app_error_code, const char *app_reason) @@ -2843,11 +2871,6 @@ void ossl_quic_channel_local_close(QUIC_CHANNEL *ch, uint64_t app_error_code, ch_start_terminating(ch, &tcause, 0); } -static void free_token(const unsigned char *buf, size_t buf_len, void *arg) -{ - OPENSSL_free((unsigned char *)buf); -} - /** * ch_restart - Restarts the QUIC channel by simulating loss of the initial * packet. This forces the packet to be regenerated with the updated protocol diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index 29b0edf878b..f85c5579ef6 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -1487,8 +1487,23 @@ static void port_default_packet_handler(QUIC_URXE *e, void *arg, */ if (hdr.token != NULL) { if (port_validate_token(&hdr, port, &e->peer, - &odcid, &scid) == 0) - goto undesirable; + &odcid, &scid) == 0) { + /* + * RFC 9000 s 8.1.3 + * When a server receives an Initial packet with an address + * validation token, it MUST attempt to validate the token, + * unless it has already completed address validation. + * If the token is invalid, then the server SHOULD proceed as + * if the client did not have a validated address, + * including potentially sending a Retry packet + * Note: If address validation is disabled, just act like + * The request is valid + */ + if (port->validate_addr == 1) { + port_send_retry(port, &e->peer, &hdr); + goto undesirable; + } + } } port_bind_channel(port, &e->peer, &scid, &hdr.dst_conn_id, -- 2.47.2