mirror of
https://github.com/openssl/openssl.git
synced 2025-01-06 13:26:43 +08:00
QUIC PORT: Partially move stateless reset handling to port
Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/22674)
This commit is contained in:
parent
a4be37b8ce
commit
6107619899
@ -273,6 +273,9 @@ void ossl_quic_channel_subtick(QUIC_CHANNEL *ch, QUIC_TICK_RESULT *r,
|
||||
/* For use by QUIC_PORT only. */
|
||||
void ossl_quic_channel_raise_net_error(QUIC_CHANNEL *ch);
|
||||
|
||||
/* For use by QUIC_PORT only. */
|
||||
void ossl_quic_channel_on_stateless_reset(QUIC_CHANNEL *ch);
|
||||
|
||||
/*
|
||||
* Queries and Accessors
|
||||
* =====================
|
||||
|
@ -89,12 +89,10 @@ static int ch_discard_el(QUIC_CHANNEL *ch,
|
||||
static void ch_on_idle_timeout(QUIC_CHANNEL *ch);
|
||||
static void ch_update_idle(QUIC_CHANNEL *ch);
|
||||
static void ch_update_ping_deadline(QUIC_CHANNEL *ch);
|
||||
static void ch_stateless_reset(QUIC_CHANNEL *ch);
|
||||
static void ch_on_terminating_timeout(QUIC_CHANNEL *ch);
|
||||
static void ch_start_terminating(QUIC_CHANNEL *ch,
|
||||
const QUIC_TERMINATE_CAUSE *tcause,
|
||||
int force_immediate);
|
||||
static int ch_stateless_reset_token_handler(const unsigned char *data, size_t datalen, void *arg);
|
||||
static void ch_on_txp_ack_tx(const OSSL_QUIC_FRAME_ACK *ack, uint32_t pn_space,
|
||||
void *arg);
|
||||
static void ch_rx_handle_version_neg(QUIC_CHANNEL *ch, OSSL_QRX_PKT *pkt);
|
||||
@ -207,47 +205,6 @@ static void chan_remove_reset_token(QUIC_CHANNEL *ch, uint64_t seq_num)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called by the demux whenever a new datagram arrives
|
||||
*
|
||||
* TODO(QUIC FUTURE): optimise this to only be called for unparsable packets
|
||||
*/
|
||||
static int ossl_unused ch_stateless_reset_token_handler(const unsigned char *data,
|
||||
size_t datalen, void *arg)
|
||||
{
|
||||
QUIC_SRT_ELEM srte;
|
||||
QUIC_CHANNEL *ch = (QUIC_CHANNEL *)arg;
|
||||
|
||||
/*
|
||||
* Perform some fast and cheap checks for a packet not being a stateless
|
||||
* reset token. RFC 9000 s. 10.3 specifies this layout for stateless
|
||||
* reset packets:
|
||||
*
|
||||
* Stateless Reset {
|
||||
* Fixed Bits (2) = 1,
|
||||
* Unpredictable Bits (38..),
|
||||
* Stateless Reset Token (128),
|
||||
* }
|
||||
*
|
||||
* It also specifies:
|
||||
* However, endpoints MUST treat any packet ending in a valid
|
||||
* stateless reset token as a Stateless Reset, as other QUIC
|
||||
* versions might allow the use of a long header.
|
||||
*
|
||||
* We can rapidly check for the minimum length and that the first pair
|
||||
* of bits in the first byte are 01 or 11.
|
||||
*
|
||||
* The function returns 1 if it is a stateless reset packet, 0 if it isn't
|
||||
* and -1 if an error was encountered.
|
||||
*/
|
||||
if (datalen < QUIC_STATELESS_RESET_TOKEN_LEN + 5 || (0100 & *data) != 0100)
|
||||
return 0;
|
||||
memset(&srte, 0, sizeof(srte));
|
||||
if (!reset_token_obfuscate(&srte, data + datalen - sizeof(srte.token)))
|
||||
return -1;
|
||||
return lh_QUIC_SRT_ELEM_retrieve(ch->srt_hash_tok, &srte) != NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* QUIC Channel Initialization and Teardown
|
||||
* ========================================
|
||||
@ -3072,12 +3029,13 @@ static void ch_save_err_state(QUIC_CHANNEL *ch)
|
||||
OSSL_ERR_STATE_save(ch->err_state);
|
||||
}
|
||||
|
||||
static void ossl_unused ch_stateless_reset(QUIC_CHANNEL *ch)
|
||||
void ossl_quic_channel_on_stateless_reset(QUIC_CHANNEL *ch)
|
||||
{
|
||||
QUIC_TERMINATE_CAUSE tcause = {0};
|
||||
|
||||
tcause.error_code = QUIC_ERR_NO_ERROR;
|
||||
ch_start_terminating(ch, &tcause, 1);
|
||||
tcause.error_code = QUIC_ERR_NO_ERROR;
|
||||
tcause.remote = 1;
|
||||
ch_start_terminating(ch, &tcause, 0);
|
||||
}
|
||||
|
||||
void ossl_quic_channel_raise_net_error(QUIC_CHANNEL *ch)
|
||||
|
@ -381,6 +381,52 @@ static void port_on_new_conn(QUIC_PORT *port, const BIO_ADDR *peer,
|
||||
}
|
||||
}
|
||||
|
||||
static int port_try_handle_stateless_reset(QUIC_PORT *port, const QUIC_URXE *e)
|
||||
{
|
||||
size_t i;
|
||||
const unsigned char *data = ossl_quic_urxe_data(e);
|
||||
void *opaque = NULL;
|
||||
|
||||
/*
|
||||
* Perform some fast and cheap checks for a packet not being a stateless
|
||||
* reset token. RFC 9000 s. 10.3 specifies this layout for stateless
|
||||
* reset packets:
|
||||
*
|
||||
* Stateless Reset {
|
||||
* Fixed Bits (2) = 1,
|
||||
* Unpredictable Bits (38..),
|
||||
* Stateless Reset Token (128),
|
||||
* }
|
||||
*
|
||||
* It also specifies:
|
||||
* However, endpoints MUST treat any packet ending in a valid
|
||||
* stateless reset token as a Stateless Reset, as other QUIC
|
||||
* versions might allow the use of a long header.
|
||||
*
|
||||
* We can rapidly check for the minimum length and that the first pair
|
||||
* of bits in the first byte are 01 or 11.
|
||||
*
|
||||
* The function returns 1 if it is a stateless reset packet, 0 if it isn't
|
||||
* and -1 if an error was encountered.
|
||||
*/
|
||||
if (e->data_len < QUIC_STATELESS_RESET_TOKEN_LEN + 5
|
||||
|| (0100 & *data) != 0100)
|
||||
return 0;
|
||||
|
||||
for (i = 0;; ++i) {
|
||||
if (!ossl_quic_srtm_lookup(port->srtm,
|
||||
(QUIC_STATELESS_RESET_TOKEN *)(data + e->data_len
|
||||
- sizeof(QUIC_STATELESS_RESET_TOKEN)),
|
||||
i, &opaque, NULL))
|
||||
break;
|
||||
|
||||
assert(opaque != NULL);
|
||||
ossl_quic_channel_on_stateless_reset((QUIC_CHANNEL *)opaque);
|
||||
}
|
||||
|
||||
return i > 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called by the demux when we get a packet not destined for any known
|
||||
* DCID.
|
||||
@ -392,6 +438,9 @@ static void port_default_packet_handler(QUIC_URXE *e, void *arg)
|
||||
QUIC_PKT_HDR hdr;
|
||||
QUIC_CHANNEL *new_ch = NULL;
|
||||
|
||||
if (port_try_handle_stateless_reset(port, e))
|
||||
goto undesirable;
|
||||
|
||||
// TODO review this
|
||||
if (port->tserver_ch == NULL)
|
||||
goto undesirable;
|
||||
|
Loading…
Reference in New Issue
Block a user