]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: quic: Missing Retry token length on receipt
authorFrédéric Lécaille <flecaille@haproxy.com>
Mon, 15 May 2023 16:11:21 +0000 (18:11 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 24 May 2023 14:30:11 +0000 (16:30 +0200)
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

index eb47f340fc44ba19e41a81826341bb8ada198638..a002555d57c41fce741f9736f38d5709633364c2 100644 (file)
@@ -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);