]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: quic: separate path for rx and tx with set_encryption_secrets
authorWilliam Lallemand <wlallemand@haproxy.org>
Wed, 14 Sep 2022 15:54:05 +0000 (17:54 +0200)
committerWilliam Lallemand <wlallemand@haproxy.org>
Wed, 14 Sep 2022 16:16:37 +0000 (18:16 +0200)
With quicTLS the set_encruption_secrets callback is always called with
the read_secret and the write_secret.

However this is not the case with libreSSL, which uses the
set_read_secret()/set_write_secret() mecanism. It still provides the
set_encryption_secrets() callback, which is called with a NULL
parameter for the write_secret during the read, and for the read_secret
during the write.

The exchange key was not designed in haproxy to be called separately for
read and write, so this patch allow calls with read or write key to
NULL.

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

index 02e155d00befd256ceab4e0070b4e10188bd520c..df836d5102511c63af1dc88be0bf531d1279f02e 100644 (file)
@@ -420,14 +420,24 @@ static inline void quic_tls_ctx_secs_free(struct quic_tls_ctx *ctx)
  */
 static inline int quic_tls_ctx_keys_alloc(struct quic_tls_ctx *ctx)
 {
+       if (ctx->rx.key)
+               goto write;
+
        if (!(ctx->rx.iv = pool_alloc(pool_head_quic_tls_iv)) ||
-           !(ctx->rx.key = pool_alloc(pool_head_quic_tls_key)) ||
-           !(ctx->tx.iv = pool_alloc(pool_head_quic_tls_iv)) ||
+           !(ctx->rx.key = pool_alloc(pool_head_quic_tls_key)))
+               goto err;
+
+ write:
+       if (ctx->tx.key)
+               goto out;
+
+       if (!(ctx->tx.iv = pool_alloc(pool_head_quic_tls_iv)) ||
            !(ctx->tx.key = pool_alloc(pool_head_quic_tls_key)))
                goto err;
 
        ctx->rx.ivlen = ctx->tx.ivlen = QUIC_TLS_IV_LEN;
        ctx->rx.keylen = ctx->tx.keylen = QUIC_TLS_KEY_LEN;
+out:
        return 1;
 
  err:
index 4cfd60f875abb9af6677c1b9f7d55fd42220ffca..042bd17aec4b391732e46cf25618fa2c0a428468 100644 (file)
@@ -919,6 +919,9 @@ int ha_quic_set_encryption_secrets(SSL *ssl, enum ssl_encryption_level_t level,
        rx->md   = tx->md   = tls_md(cipher);
        rx->hp   = tx->hp   = tls_hp(cipher);
 
+       if (!read_secret)
+               goto write;
+
        if (!quic_tls_derive_keys(rx->aead, rx->hp, rx->md, ver, rx->key, rx->keylen,
                                  rx->iv, rx->ivlen, rx->hp_key, sizeof rx->hp_key,
                                  read_secret, secret_len)) {
@@ -945,6 +948,8 @@ int ha_quic_set_encryption_secrets(SSL *ssl, enum ssl_encryption_level_t level,
                quic_accept_push_qc(qc);
        }
 
+write:
+
        if (!write_secret)
                goto out;
 
@@ -977,17 +982,17 @@ int ha_quic_set_encryption_secrets(SSL *ssl, enum ssl_encryption_level_t level,
                        goto leave;
                }
 
-               memcpy(rx->secret, read_secret, secret_len);
-               rx->secretlen = secret_len;
-               memcpy(tx->secret, write_secret, secret_len);
-               tx->secretlen = secret_len;
+               if (read_secret) {
+                       memcpy(rx->secret, read_secret, secret_len);
+                       rx->secretlen = secret_len;
+               }
+               if (write_secret) {
+                       memcpy(tx->secret, write_secret, secret_len);
+                       tx->secretlen = secret_len;
+               }
                /* Initialize all the secret keys lengths */
                prv_rx->secretlen = nxt_rx->secretlen = nxt_tx->secretlen = secret_len;
                /* Prepare the next key update */
-               if (!quic_tls_key_update(qc)) {
-                       // trace already emitted by function above
-                       goto leave;
-               }
        }
 
  out:
@@ -2258,6 +2263,11 @@ static inline int qc_provide_cdata(struct quic_enc_level *el,
                else {
                        qc->state = QUIC_HS_ST_COMPLETE;
                }
+
+               if (!quic_tls_key_update(qc)) {
+                       TRACE_ERROR("quic_tls_key_update() failed", QUIC_EV_CONN_IO_CB, qc);
+                       goto leave;
+               }
        } else {
                ssl_err = SSL_process_quic_post_handshake(ctx->ssl);
                if (ssl_err != 1) {