From 5ff1c9778ca6753f0a43d619f47b0191fef35488 Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Tue, 11 Jan 2022 14:11:32 +0100 Subject: [PATCH] MEDIUM: quic: implement Initial token parsing Implement the parsing of token from Initial packets. It is expected that the token contains a CID which is the DCID from the Initial packet received from the client without token which triggers a Retry packet. This CID is then used for transport parameters. Note that at the moment Retry packet emission is not implemented. This will be achieved in a following commit. --- include/haproxy/xprt_quic-t.h | 1 + src/xprt_quic.c | 37 +++++++++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/include/haproxy/xprt_quic-t.h b/include/haproxy/xprt_quic-t.h index 06c43fe59..78ced5160 100644 --- a/include/haproxy/xprt_quic-t.h +++ b/include/haproxy/xprt_quic-t.h @@ -435,6 +435,7 @@ struct quic_rx_packet { /* Packet number length */ uint32_t pnl; uint64_t token_len; + const unsigned char *token; /* Packet length */ uint64_t len; /* Packet length before decryption */ diff --git a/src/xprt_quic.c b/src/xprt_quic.c index 558e7048f..6cf0d4bb7 100644 --- a/src/xprt_quic.c +++ b/src/xprt_quic.c @@ -4046,6 +4046,25 @@ static struct quic_conn *retrieve_qc_conn_from_cid(struct quic_rx_packet *pkt, return qc; } +/* Parse the Retry token from buffer whose size is . This + * will extract the parameters stored in the token : . + * + * Returns 0 on success else non-zero. + */ +static int parse_retry_token(const unsigned char *token, uint64_t token_len, + struct quic_cid *odcid) +{ + uint64_t odcid_len; + + if (!quic_dec_int(&odcid_len, &token, token + token_len)) + return 1; + + memcpy(odcid->data, token, odcid_len); + odcid->len = odcid_len; + + return 0; +} + static ssize_t qc_lstnr_pkt_rcv(unsigned char *buf, const unsigned char *end, struct quic_rx_packet *pkt, struct quic_dgram_ctx *dgram_ctx, @@ -4127,6 +4146,10 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char *buf, const unsigned char *end, * The token must be provided in a Retry packet or NEW_TOKEN frame. */ pkt->token_len = token_len; + if (pkt->token_len) { + pkt->token = buf; + buf += pkt->token_len; + } } else if (pkt->type != QUIC_PACKET_TYPE_0RTT) { if (pkt->dcid.len != QUIC_HAP_CID_LEN) { @@ -4168,9 +4191,19 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char *buf, const unsigned char *end, odcid = &qc->rx.params.original_destination_connection_id; /* Copy the transport parameters. */ qc->rx.params = l->bind_conf->quic_params; + /* Copy original_destination_connection_id transport parameter. */ - memcpy(odcid->data, &pkt->dcid.data, pkt->dcid.len); - odcid->len = pkt->dcid.len; + if (pkt->token_len) { + if (parse_retry_token(pkt->token, pkt->token_len, odcid)) { + TRACE_PROTO("Error during Initial token parsing", QUIC_EV_CONN_LPKT, qc); + goto err; + } + } + else { + memcpy(odcid->data, &pkt->dcid.data, pkt->dcid.len); + odcid->len = pkt->dcid.len; + } + /* Copy the initial source connection ID. */ quic_cid_cpy(&qc->rx.params.initial_source_connection_id, &qc->scid); qc->enc_params_len =