From 35b63964a00bb0e5f9478272b1f838d13e923b79 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fr=C3=A9d=C3=A9ric=20L=C3=A9caille?= Date: Mon, 15 May 2023 18:11:21 +0200 Subject: [PATCH] BUG/MINOR: quic: Missing Retry token length on receipt quic_retry_token_check() must decipher the token sent to and received back from clients. This token is made of the token format byte, the ODCID prefixed by its one byte length, the timestamp of its creation, and terminated by an AEAD TAG followed by the salt used to derive the secret to cipher the token. So, the length of these data must be between 2 + QUIC_ODCID_MINLEN + sizeof(uint32_t) + QUIC_TLS_TAG_LEN + QUIC_RETRY_TOKEN_SALTLEN and 2 + QUIC_CID_MAXLEN + sizeof(uint32_t) + QUIC_TLS_TAG_LEN + QUIC_RETRY_TOKEN_SALTLEN. Must be backported to 2.7 and 2.6. --- src/quic_conn.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/quic_conn.c b/src/quic_conn.c index eb47f340fc..a002555d57 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -6508,6 +6508,16 @@ static int quic_retry_token_check(struct quic_rx_packet *pkt, goto err; } + /* The token is made of the token format byte, the ODCID prefixed by its one byte + * length, the creation timestamp, an AEAD TAG, and finally + * the random bytes used to derive the secret to encrypt the token. + */ + if (tokenlen < 2 + QUIC_ODCID_MINLEN + sizeof(uint32_t) + QUIC_TLS_TAG_LEN + QUIC_RETRY_TOKEN_SALTLEN || + tokenlen > 2 + QUIC_CID_MAXLEN + sizeof(uint32_t) + QUIC_TLS_TAG_LEN + QUIC_RETRY_TOKEN_SALTLEN) { + TRACE_ERROR("invalid token length", QUIC_EV_CONN_LPKT, qc); + goto err; + } + aadlen = quic_generate_retry_token_aad(aad, qv->num, &pkt->scid, &dgram->saddr); salt = token + tokenlen - QUIC_RETRY_TOKEN_SALTLEN; if (!quic_tls_derive_retry_token_secret(EVP_sha256(), key, sizeof key, iv, sizeof iv, @@ -6521,7 +6531,7 @@ static int quic_retry_token_check(struct quic_rx_packet *pkt, goto err; } - /* Do not decrypt the QUIC_TOKEN_FMT_RETRY byte */ + /* The token is prefixed by a one-byte length format which is not ciphered. */ if (!quic_tls_decrypt2(buf, token + 1, tokenlen - QUIC_RETRY_TOKEN_SALTLEN - 1, aad, aadlen, ctx, aead, key, iv)) { TRACE_ERROR("Could not decrypt retry token", QUIC_EV_CONN_LPKT, qc); -- 2.47.3