From: Neil Horman Date: Tue, 5 Nov 2024 21:25:25 +0000 (-0500) Subject: Generate initial packet keys based on new dcid for addr validation X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5c75b530eb7a1feab969bf9418e5286d4c417609;p=thirdparty%2Fopenssl.git Generate initial packet keys based on new dcid for addr validation When using retry packets in QUIC to implement address validation, the 2nd inital packet that arrives after the server sends the retry frame will have its CRYPTO packet encrypted using keys derived from the new dcid, rather than the dcid in the 1st initial packet. Update the channel creation code to update those keys on the server so that the CRYPTO packet is decrypted successfully Reviewed-by: Saša Nedvědický Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/25890) --- diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index 08b084d01e3..3e47b25a635 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -3389,11 +3389,14 @@ static void ch_on_idle_timeout(QUIC_CHANNEL *ch) * @param peer Address of the peer to which the channel connects. * @param peer_scid Peer-specified source connection ID. * @param peer_dcid Peer-specified destination connection ID. + * @param peer_odcid Peer-specified original destination connection ID + * may be NULL if retry frame not sent to client * @return 1 on success, 0 on failure to set required elements. */ static int ch_on_new_conn_common(QUIC_CHANNEL *ch, const BIO_ADDR *peer, const QUIC_CONN_ID *peer_scid, - const QUIC_CONN_ID *peer_dcid) + const QUIC_CONN_ID *peer_dcid, + const QUIC_CONN_ID *peer_odcid) { /* Note our newly learnt peer address and CIDs. */ ch->cur_peer_addr = *peer; @@ -3424,7 +3427,9 @@ static int ch_on_new_conn_common(QUIC_CHANNEL *ch, const BIO_ADDR *peer, return 0; /* Register the peer ODCID in the LCIDM. */ - if (!ossl_quic_lcidm_enrol_odcid(ch->lcidm, ch, &ch->init_dcid)) + if (!ossl_quic_lcidm_enrol_odcid(ch->lcidm, ch, peer_odcid == NULL ? + &ch->init_dcid : + peer_odcid)) return 0; /* Change state. */ @@ -3445,9 +3450,32 @@ int ossl_quic_channel_on_new_conn(QUIC_CHANNEL *ch, const BIO_ADDR *peer, if (!ossl_quic_lcidm_generate_initial(ch->lcidm, ch, &ch->cur_local_cid)) return 0; - return ch_on_new_conn_common(ch, peer, peer_scid, peer_dcid); + return ch_on_new_conn_common(ch, peer, peer_scid, peer_dcid, NULL); } +/** + * Binds a QUIC channel to a specific peer's address and connection IDs. + * + * This function is used to establish a binding between a QUIC channel and a + * peer's address and connection IDs. The binding is performed only if the + * channel is idle and is on the server side. The peer's destination connection + * ID (`peer_dcid`) is mandatory, and the channel's current local connection ID + * is set to this value. + * + * @param ch Pointer to the QUIC_CHANNEL structure representing the + * channel to be bound. + * @param peer Pointer to a BIO_ADDR structure representing the peer's + * address. + * @param peer_scid Pointer to the peer's source connection ID (QUIC_CONN_ID). + * @param peer_dcid Pointer to the peer's destination connection ID + * (QUIC_CONN_ID). This must not be NULL. + * @param peer_odcid Pointer to the original destination connection ID + * (QUIC_CONN_ID) chosen by the peer in its first initial + * packet received without a token. + * + * @return 1 on success, or 0 on failure if the conditions for binding are not + * met (e.g., channel is not idle or not a server, or binding fails). + */ int ossl_quic_bind_channel(QUIC_CHANNEL *ch, const BIO_ADDR *peer, const QUIC_CONN_ID *peer_scid, const QUIC_CONN_ID *peer_dcid, @@ -3467,7 +3495,7 @@ int ossl_quic_bind_channel(QUIC_CHANNEL *ch, const BIO_ADDR *peer, * peer_odcid <=> is initial dst conn id chosen by peer in its * first initial packet we received without token. */ - return ch_on_new_conn_common(ch, peer, peer_scid, peer_odcid); + return ch_on_new_conn_common(ch, peer, peer_scid, peer_dcid, peer_odcid); } SSL *ossl_quic_channel_get0_ssl(QUIC_CHANNEL *ch)