From f0c52f716050df1d2bbc3b3dc7183400c1931ac6 Mon Sep 17 00:00:00 2001 From: Frederic Lecaille Date: Fri, 14 Nov 2025 17:21:53 +0100 Subject: [PATCH] BUG/MINOR: quic-be: missing version negotiation This bug impacts only the QUIC clients (or backends). The version negotiation was not supported at all for them. This is an oversight. Contrary to the QUIC server which choose the negotiated version after having received the transport parameters (into ClientHello message) the client selects the negotiated version from the first Initial packet version field. Indeed, the server transport parameters are inside the ServerHello messages ciphered into Handshake packets. This non intrusive patch does not impact the QUIC server implementation. It only selects the negotiated version from the first Initial packet received from the server and consequently initializes the TLS cipher context. Thank you to @InputOutputZ for having reporte this issue in GH #3178. No need to backport because the QUIC backends support arrives with 3.3. --- src/quic_rx.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/quic_rx.c b/src/quic_rx.c index ec4a0f4e7..c1dd4d0fa 100644 --- a/src/quic_rx.c +++ b/src/quic_rx.c @@ -2077,6 +2077,28 @@ static int quic_rx_pkt_parse(struct quic_conn *qc, struct quic_rx_packet *pkt, memcpy(qc->dcid.data, pkt->scid.data, pkt->scid.len); qc->dcid.len = pkt->scid.len; } + + /* Identify the negotiated version, chosen and sent by the server */ + if (qc_is_back(qc) && pkt->version != qc->original_version && !qc->nictx) { + qc->nictx = pool_alloc(pool_head_quic_tls_ctx); + if (!qc->nictx) { + TRACE_PROTO("Could not alloc a new Initial secrets TLS context", + QUIC_EV_CONN_RXPKT, qc); + goto drop; + } + + quic_tls_ctx_reset(qc->nictx); + if (!qc_new_isecs(qc, qc->nictx, pkt->version, + qc->odcid.data, qc->odcid.len, 0)) { + TRACE_PROTO("Could not derive Initial secrets for new version", + QUIC_EV_CONN_RXPKT, qc); + goto drop; + } + + TRACE_PROTO("new Initial secrets TLS context initialization done", + QUIC_EV_CONN_RXPKT, qc); + qc->negotiated_version = pkt->version; + } } } else if (pkt->type == QUIC_PACKET_TYPE_0RTT) {