From: Emeric Brun Date: Thu, 7 Sep 2023 08:08:29 +0000 (+0200) Subject: MINOR: quic: handle external extra CIDs generator. X-Git-Tag: v2.9-dev6~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=27b2fd2e064bd102c7c06899041294aab68efb9d;p=thirdparty%2Fhaproxy.git MINOR: quic: handle external extra CIDs generator. This patch adds the ability to externalize and customize the code of the computation of extra CIDs after the first one was derived from the ODCID. This is to prepare interoperability with extra components such as different QUIC proxies or routers for instance. To process the patch defines two function callbacks: - the first one to compute a hash 64bits from the first generated CID (itself continues to be derived from ODCID). Resulting hash is stored into the 'quic_conn' and 64bits is chosen large enought to be able to store an entire haproxy's CID. - the second callback re-uses the previoulsy computed hash to derive an extra CID using the custom algorithm. If not set haproxy will continue to choose a randomized CID value. Those two functions have also the 'cluster_secret' passed as an argument: this way, it is usable for obfuscation or ciphering. --- diff --git a/include/haproxy/quic_conn-t.h b/include/haproxy/quic_conn-t.h index 5373d42f72..36e74431f6 100644 --- a/include/haproxy/quic_conn-t.h +++ b/include/haproxy/quic_conn-t.h @@ -520,6 +520,10 @@ struct quic_conn { #endif uint64_t next_cid_seq_num; + /* Initial hash computed from first ID (derived from ODCID). + * it could be reused to derive extra CIDs from the same hash + */ + uint64_t hash64; /* Initial encryption level */ struct quic_enc_level *iel; diff --git a/include/haproxy/quic_conn.h b/include/haproxy/quic_conn.h index 5353a5969b..5d2fbfa05b 100644 --- a/include/haproxy/quic_conn.h +++ b/include/haproxy/quic_conn.h @@ -619,5 +619,10 @@ static inline void quic_handle_stopping(void) int qc_set_tid_affinity(struct quic_conn *qc, uint new_tid, struct listener *new_li); void qc_finalize_affinity_rebind(struct quic_conn *qc); +/* Function pointer that can be used to compute a hash from first generated CID (derived from ODCID) */ +extern uint64_t (*quic_hash64_from_cid)(const unsigned char *cid, int size, const unsigned char *secret, size_t secretlen); +/* Function pointer that can be used to derive a new CID from the previously computed hash */ +extern void (*quic_newcid_from_hash64)(unsigned char *cid, int size, uint64_t hash, const unsigned char *secret, size_t secretlen); + #endif /* USE_QUIC */ #endif /* _HAPROXY_QUIC_CONN_H */ diff --git a/src/quic_conn.c b/src/quic_conn.c index 23d1400950..051c9da579 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -116,6 +116,10 @@ const struct quic_version quic_versions[] = { }, }; +/* Function pointers, can be used to compute a hash from first generated CID and to derive new CIDs */ +uint64_t (*quic_hash64_from_cid)(const unsigned char *cid, int size, const unsigned char *secret, size_t secretlen) = NULL; +void (*quic_newcid_from_hash64)(unsigned char *cid, int size, uint64_t hash, const unsigned char *secret, size_t secretlen) = NULL; + /* The total number of supported versions */ const size_t quic_versions_nb = sizeof quic_versions / sizeof *quic_versions; /* Listener only preferred version */ @@ -644,8 +648,11 @@ struct quic_connection_id *new_quic_cid(struct eb_root *root, conn_id->cid.len = QUIC_HAP_CID_LEN; if (!orig) { - /* TODO: RAND_bytes() should be replaced */ - if (RAND_bytes(conn_id->cid.data, conn_id->cid.len) != 1) { + if (quic_newcid_from_hash64) + quic_newcid_from_hash64(conn_id->cid.data, conn_id->cid.len, qc->hash64, + global.cluster_secret, sizeof(global.cluster_secret)); + else if (RAND_bytes(conn_id->cid.data, conn_id->cid.len) != 1) { + /* TODO: RAND_bytes() should be replaced */ TRACE_ERROR("RAND_bytes() failed", QUIC_EV_CONN_TXPKT, qc); goto err; } diff --git a/src/quic_rx.c b/src/quic_rx.c index 39271a0fd4..7dbf94d808 100644 --- a/src/quic_rx.c +++ b/src/quic_rx.c @@ -1964,6 +1964,11 @@ static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt, goto err; } + /* Compute and store into the quic_conn the hash used to compute extra CIDs */ + if (quic_hash64_from_cid) + qc->hash64 = quic_hash64_from_cid(conn_id->cid.data, conn_id->cid.len, + global.cluster_secret, sizeof(global.cluster_secret)); + tree = &quic_cid_trees[quic_cid_tree_idx(&conn_id->cid)]; HA_RWLOCK_WRLOCK(QC_CID_LOCK, &tree->lock); node = ebmb_insert(&tree->root, &conn_id->node, conn_id->cid.len);