]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: Make QUIC-TLS support at least two initial salts
authorFrédéric Lécaille <flecaille@haproxy.com>
Tue, 31 Aug 2021 17:10:40 +0000 (19:10 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 23 Sep 2021 13:27:25 +0000 (15:27 +0200)
These salts are used to derive initial secrets to decrypt the first Initial packet.
We support draft-29 and v1 QUIC version initial salts.
Add parameters to our QUIC-TLS API functions used to derive these secret for
these salts.
Make our xprt_quic use the correct initial salt upon QUIC version field found in
the first paquet. Useful to support connections with curl which use draft-29
QUIC version.

include/haproxy/quic_tls.h
include/haproxy/xprt_quic-t.h
src/quic_tls.c
src/xprt_quic.c

index 288cc16c0455ff6ca5d0562f86ded2961606577b..def95fe443f3d553ddc58af0cd2c7079397dca73 100644 (file)
 #include <haproxy/trace.h>
 #include <haproxy/xprt_quic.h>
 
+/* Initial salt depending on QUIC version to derive client/server initial secrets.
+ * This one is for draft-29 QUIC version.
+ */
+unsigned char initial_salt_draft_29[20] = {
+       0xaf, 0xbf, 0xec, 0x28, 0x99, 0x93, 0xd2, 0x4c,
+       0x9e, 0x97, 0x86, 0xf1, 0x9c, 0x61, 0x11, 0xe0,
+       0x43, 0x90, 0xa8, 0x99
+};
+
+unsigned char initial_salt_v1[20] = {
+       0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3,
+       0x4d, 0x17, 0x9a, 0xe6, 0xa4, 0xc8, 0x0c, 0xad,
+       0xcc, 0xbb, 0x7f, 0x0a
+};
+
 void quic_tls_keys_hexdump(struct buffer *buf, struct quic_tls_secrets *secs);
 
 void quic_tls_secret_hexdump(struct buffer *buf,
                              const unsigned char *secret, size_t secret_len);
 
 int quic_derive_initial_secret(const EVP_MD *md,
+                               const unsigned char *initial_salt, size_t initial_salt_sz,
                                unsigned char *initial_secret, size_t initial_secret_sz,
                                const unsigned char *secret, size_t secret_sz);
 
@@ -390,6 +406,7 @@ static inline void quic_tls_discard_keys(struct quic_enc_level *qel)
  * Return 1 if succeeded or 0 if not.
  */
 static inline int qc_new_isecs(struct quic_conn *qc,
+                               const unsigned char *salt, size_t salt_len,
                                const unsigned char *cid, size_t cidlen, int server)
 {
        unsigned char initial_secret[32];
@@ -404,6 +421,7 @@ static inline int qc_new_isecs(struct quic_conn *qc,
        ctx = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL].tls_ctx;
        quic_initial_tls_ctx_init(ctx);
        if (!quic_derive_initial_secret(ctx->rx.md,
+                                       salt, salt_len,
                                        initial_secret, sizeof initial_secret,
                                        cid, cidlen))
                goto err;
index b64da75eb27425a4222508816bd34bd3d61e43c8..b06245554d3bdb83820d8fd9e5e0a6844c8e40e2 100644 (file)
@@ -42,6 +42,8 @@
 #include <import/ebmbtree.h>
 
 #define QUIC_PROTOCOL_VERSION_DRAFT_28   0xff00001c /* draft-28 */
+#define QUIC_PROTOCOL_VERSION_DRAFT_29   0xff00001d /* draft-29 */
+#define QUIC_PROTOCOL_VERSION_1          0x00000001 /* V1 */
 
 #define QUIC_INITIAL_IPV4_MTU      1252 /* (bytes) */
 #define QUIC_INITIAL_IPV6_MTU      1232
index 11d5875daebd134ddf88d538b9fac9faff6ec515..bd45fcee98486b1f368e413e1c43c70bf9740b20 100644 (file)
 __attribute__((format (printf, 3, 4)))
 void hexdump(const void *buf, size_t buflen, const char *title_fmt, ...);
 
-/* Initial salt depending on QUIC version to derive client/server initial secrets.
- * This one is for draft-29 QUIC version.
- */
-unsigned char initial_salt[20] = {
-       0xaf, 0xbf, 0xec, 0x28, 0x99, 0x93, 0xd2, 0x4c,
-       0x9e, 0x97, 0x86, 0xf1, 0x9c, 0x61, 0x11, 0xe0,
-       0x43, 0x90, 0xa8, 0x99
-};
-
-unsigned char initial_salt_v1[20] = {
-       0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3,
-       0x4d, 0x17, 0x9a, 0xe6, 0xa4, 0xc8, 0x0c, 0xad,
-       0xcc, 0xbb, 0x7f, 0x0a
-};
-
 /* Dump the RX/TX secrets of <secs> QUIC TLS secrets. */
 void quic_tls_keys_hexdump(struct buffer *buf, struct quic_tls_secrets *secs)
 {
@@ -67,7 +52,7 @@ void quic_tls_secret_hexdump(struct buffer *buf,
 int quic_hkdf_extract(const EVP_MD *md,
                       unsigned char *buf, size_t *buflen,
                       const unsigned char *key, size_t keylen,
-                      unsigned char *salt, size_t saltlen)
+                      const unsigned char *salt, size_t saltlen)
 {
        return HKDF_extract(buf, buflen, md, key, keylen, salt, saltlen);
 }
@@ -83,7 +68,7 @@ int quic_hkdf_expand(const EVP_MD *md,
 int quic_hkdf_extract(const EVP_MD *md,
                       unsigned char *buf, size_t *buflen,
                       const unsigned char *key, size_t keylen,
-                      unsigned char *salt, size_t saltlen)
+                      const unsigned char *salt, size_t saltlen)
 {
     EVP_PKEY_CTX *ctx;
 
@@ -224,11 +209,12 @@ int quic_tls_derive_keys(const EVP_CIPHER *aead, const EVP_CIPHER *hp,
  * Returns the size of the derived secret if succeeded, 0 if not.
  */
 int quic_derive_initial_secret(const EVP_MD *md,
+                               const unsigned char *initial_salt, size_t initial_salt_sz,
                                unsigned char *initial_secret, size_t initial_secret_sz,
                                const unsigned char *secret, size_t secret_sz)
 {
        if (!quic_hkdf_extract(md, initial_secret, &initial_secret_sz, secret, secret_sz,
-                              initial_salt_v1, sizeof initial_salt_v1))
+                              initial_salt, initial_salt_sz))
                return 0;
 
        return 1;
index 7654940804086051d48eb1123ac555d75c3d11aa..ee7004bf4e91803beac5b9c38604b2113a42eaad 100644 (file)
@@ -3371,6 +3371,8 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char **buf, const unsigned char *end,
                        int ipv4;
                        struct quic_cid *odcid;
                        struct ebmb_node *n = NULL;
+                       const unsigned char *salt = initial_salt_v1;
+                       size_t salt_len = sizeof initial_salt_v1;
 
                        if (pkt->type != QUIC_PACKET_TYPE_INITIAL) {
                                TRACE_PROTO("Non Initiial packet", QUIC_EV_CONN_LPKT);
@@ -3406,7 +3408,12 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char **buf, const unsigned char *end,
                        /* NOTE: the socket address has been concatenated to the destination ID
                         * chosen by the client for Initial packets.
                         */
-                       if (!qc_new_isecs(qc, pkt->dcid.data, pkt->odcid_len, 1)) {
+                       if (pkt->version == QUIC_PROTOCOL_VERSION_DRAFT_29) {
+                               salt = initial_salt_draft_29;
+                               salt_len = sizeof initial_salt_draft_29;
+                       }
+                       if (!qc_new_isecs(qc, salt, salt_len,
+                                         pkt->dcid.data, pkt->odcid_len, 1)) {
                                TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT, qc->conn);
                                goto err;
                        }
@@ -4360,7 +4367,8 @@ static int qc_conn_init(struct connection *conn, void **xprt_ctx)
 
                conn->qc = qc;
                qc->conn = conn;
-               if (!qc_new_isecs(qc, dcid, sizeof dcid, 0))
+               if (!qc_new_isecs(qc, initial_salt_v1, sizeof initial_salt_v1,
+                                 dcid, sizeof dcid, 0))
                        goto err;
 
                if (ssl_bio_and_sess_init(conn, srv->ssl_ctx.ctx,