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.
This commit is contained in:
Emeric Brun 2023-09-07 10:08:29 +02:00 committed by Willy Tarreau
parent d897d7da87
commit 27b2fd2e06
4 changed files with 23 additions and 2 deletions

View File

@ -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;

View File

@ -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 */

View File

@ -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;
}

View File

@ -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);