diff --git a/include/haproxy/quic_conn-t.h b/include/haproxy/quic_conn-t.h index 5373d42f7..36e74431f 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 5353a5969..5d2fbfa05 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 23d140095..051c9da57 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 39271a0fd..7dbf94d80 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);