From: Frédéric Lécaille Date: Tue, 4 Jul 2023 05:55:58 +0000 (+0200) Subject: MINOR: quic: Dynamic allocation for negotiated Initial TLS cipher context. X-Git-Tag: v2.9-dev2~30 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=90a63ae4faee2e86db3d8326fb9b9d7cf05630f1;p=thirdparty%2Fhaproxy.git MINOR: quic: Dynamic allocation for negotiated Initial TLS cipher context. Shorten ->negotiated_ictx quic_conn struct member (->nictx). This variable is used during version negotiation. Indeed, a connection may have to support support several QUIC versions of paquets during the handshake. ->nictx is the QUIC TLS cipher context used for the negotiated QUIC version. This patch allows a connection to dynamically allocate this TLS cipher context. Add a new pool (pool_head_quic_tls_ctx) for such QUIC TLS cipher context object. Modify qc_new_conn() to initialize ->nictx to NULL value. quic_tls_ctx_secs_free() frees all the secrets attached to a QUIC TLS cipher context. Modify it to do nothing if it is called with a NULL TLS cipher context. Modify to allocate ->nictx from qc_conn_finalize() just before initializing its secrets. qc_conn_finalize() allocates -nictx only if needed (if a new QUIC version was negotiated). Modify qc_conn_release() which release a QUIC connection (quic_conn struct) to release ->nictx TLS cipher context. --- diff --git a/include/haproxy/quic_conn-t.h b/include/haproxy/quic_conn-t.h index 3d830ebbc3..5b71ae8e58 100644 --- a/include/haproxy/quic_conn-t.h +++ b/include/haproxy/quic_conn-t.h @@ -581,7 +581,7 @@ struct quic_conn { const struct quic_version *original_version; const struct quic_version *negotiated_version; /* Negotiated version Initial TLS context */ - struct quic_tls_ctx negotiated_ictx; + struct quic_tls_ctx *nictx; /* Connection owned socket FD. */ int fd; /* QUIC transport parameters TLS extension */ diff --git a/include/haproxy/quic_tls-t.h b/include/haproxy/quic_tls-t.h index 1e146ae8a7..b36505f88f 100644 --- a/include/haproxy/quic_tls-t.h +++ b/include/haproxy/quic_tls-t.h @@ -54,6 +54,7 @@ extern struct pool_head *pool_head_quic_pktns; extern struct pool_head *pool_head_quic_enc_level; +extern struct pool_head *pool_head_quic_tls_ctx; extern struct pool_head *pool_head_quic_tls_secret; extern struct pool_head *pool_head_quic_tls_iv; extern struct pool_head *pool_head_quic_tls_key; diff --git a/include/haproxy/quic_tls.h b/include/haproxy/quic_tls.h index 4d1af10fe0..d433fff3d4 100644 --- a/include/haproxy/quic_tls.h +++ b/include/haproxy/quic_tls.h @@ -648,6 +648,9 @@ static inline void quic_tls_ctx_reset(struct quic_tls_ctx *ctx) */ static inline void quic_tls_ctx_secs_free(struct quic_tls_ctx *ctx) { + if (!ctx) + return; + if (ctx->rx.iv) { memset(ctx->rx.iv, 0, ctx->rx.ivlen); ctx->rx.ivlen = 0; diff --git a/src/quic_conn.c b/src/quic_conn.c index 8885b7655d..da471bb818 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -1582,7 +1582,7 @@ static inline struct quic_tls_ctx *qc_select_tls_ctx(struct quic_conn *qc, struct quic_rx_packet *pkt) { return pkt->type != QUIC_PACKET_TYPE_INITIAL ? &qel->tls_ctx : - pkt->version == qc->negotiated_version ? &qc->negotiated_ictx : &qel->tls_ctx; + pkt->version == qc->negotiated_version ? qc->nictx : &qel->tls_ctx; } /* Decrypt packet using encryption level for connection. @@ -2385,10 +2385,16 @@ static int qc_conn_finalize(struct quic_conn *qc, int server) if (qc->flags & QUIC_FL_CONN_FINALIZED) goto finalized; - if (qc->negotiated_version && - !qc_new_isecs(qc, &qc->negotiated_ictx, qc->negotiated_version, - qc->odcid.data, qc->odcid.len, server)) - goto out; + if (qc->negotiated_version) { + qc->nictx = pool_alloc(pool_head_quic_tls_ctx); + if (!qc->nictx) + goto out; + + quic_tls_ctx_reset(qc->nictx); + if (!qc_new_isecs(qc, qc->nictx, qc->negotiated_version, + qc->odcid.data, qc->odcid.len, server)) + goto out; + } /* This connection is functional (ready to send/receive) */ qc->flags |= QUIC_FL_CONN_FINALIZED; @@ -3641,7 +3647,7 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf, if (qc->negotiated_version) { ver = qc->negotiated_version; if (qel == qc->iel) - tls_ctx = &qc->negotiated_ictx; + tls_ctx = qc->nictx; else tls_ctx = &qel->tls_ctx; } @@ -5466,7 +5472,7 @@ static struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4, } /* Initialize in priority qc members required for a safe dealloc. */ - + qc->nictx = NULL; /* Prevents these CID to be dumped by TRACE() calls */ qc->scid.len = qc->odcid.len = qc->dcid.len = 0; /* required to use MTLIST_IN_LIST */ @@ -5509,8 +5515,6 @@ static struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4, qc->ipktns = qc->hpktns = qc->apktns = NULL; LIST_INIT(&qc->pktns_list); - quic_tls_ctx_reset(&qc->negotiated_ictx); - /* Required to safely call quic_conn_prx_cntrs_update() from quic_conn_release(). */ qc->prx_counters = NULL; @@ -5762,7 +5766,9 @@ void quic_conn_release(struct quic_conn *qc) qc_enc_level_free(qc, &qc->hel); qc_enc_level_free(qc, &qc->ael); - quic_tls_ctx_secs_free(&qc->negotiated_ictx); + quic_tls_ctx_secs_free(qc->nictx); + pool_free(pool_head_quic_tls_ctx, qc->nictx); + qc->nictx = NULL; quic_pktns_release(qc, &qc->ipktns); quic_pktns_release(qc, &qc->hpktns); diff --git a/src/quic_tls.c b/src/quic_tls.c index 6eda50f2f4..ba50099398 100644 --- a/src/quic_tls.c +++ b/src/quic_tls.c @@ -14,6 +14,7 @@ DECLARE_POOL(pool_head_quic_enc_level, "quic_enc_level", sizeof(struct quic_enc_level)); DECLARE_POOL(pool_head_quic_pktns, "quic_pktns", sizeof(struct quic_pktns)); +DECLARE_POOL(pool_head_quic_tls_ctx, "quic_tls_ctx", sizeof(struct quic_tls_ctx)); DECLARE_POOL(pool_head_quic_tls_secret, "quic_tls_secret", QUIC_TLS_SECRET_LEN); DECLARE_POOL(pool_head_quic_tls_iv, "quic_tls_iv", QUIC_TLS_IV_LEN); DECLARE_POOL(pool_head_quic_tls_key, "quic_tls_key", QUIC_TLS_KEY_LEN);