]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic_tls: Make key update use of reusable cipher contexts
authorFrédéric Lécaille <flecaille@haproxy.com>
Tue, 5 Apr 2022 14:28:38 +0000 (16:28 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 8 Apr 2022 13:38:29 +0000 (15:38 +0200)
We modify the key update feature implementation to support reusable cipher contexts
as this is done for the other cipher contexts for packet decryption and encryption.
To do so we attach a context to the quic_tls_kp struct and initialize it each time
the underlying secret key is updated. Same thing when we rotate the secrets keys,
we rotate the contexts as the same time.

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

index 95fefc486e51e5e3195b466a39cae1b23e3deaf3..693bc4f72dac5b76bad3b3b9434f047844adee23 100644 (file)
@@ -96,6 +96,7 @@ extern unsigned char initial_salt[20];
 
 /* Key phase used for Key Update */
 struct quic_tls_kp {
+       EVP_CIPHER_CTX *ctx;
        unsigned char *secret;
        size_t secretlen;
        unsigned char *iv;
index d12d6e07b73af7f88650d3f8de954e4f53ca0ea8..8616aa31fa053ffe034568765afc8764665c618a 100644 (file)
@@ -546,12 +546,15 @@ static inline int qc_new_isecs(struct quic_conn *qc,
  */
 static inline void quic_tls_ku_free(struct quic_conn *qc)
 {
+       EVP_CIPHER_CTX_free(qc->ku.prv_rx.ctx);
        pool_free(pool_head_quic_tls_secret, qc->ku.prv_rx.secret);
        pool_free(pool_head_quic_tls_iv,     qc->ku.prv_rx.iv);
        pool_free(pool_head_quic_tls_key,    qc->ku.prv_rx.key);
+       EVP_CIPHER_CTX_free(qc->ku.nxt_rx.ctx);
        pool_free(pool_head_quic_tls_secret, qc->ku.nxt_rx.secret);
        pool_free(pool_head_quic_tls_iv,     qc->ku.nxt_rx.iv);
        pool_free(pool_head_quic_tls_key,    qc->ku.nxt_rx.key);
+       EVP_CIPHER_CTX_free(qc->ku.nxt_tx.ctx);
        pool_free(pool_head_quic_tls_secret, qc->ku.nxt_tx.secret);
        pool_free(pool_head_quic_tls_iv,     qc->ku.nxt_tx.iv);
        pool_free(pool_head_quic_tls_key,    qc->ku.nxt_tx.key);
index e1cdc72e8ccc6e9794757b0aef1da1a84fba7952..63cfc7fe7e0a31952e74d351bf95f5c51b2cedd4 100644 (file)
@@ -733,6 +733,26 @@ static int quic_tls_key_update(struct quic_conn *qc)
                return 0;
        }
 
+       if (nxt_rx->ctx) {
+               EVP_CIPHER_CTX_free(nxt_rx->ctx);
+               nxt_rx->ctx = NULL;
+       }
+
+       if (!quic_tls_rx_ctx_init(&nxt_rx->ctx, tls_ctx->rx.aead, nxt_rx->key)) {
+               TRACE_DEVEL("could not initial RX TLS cipher context", QUIC_EV_CONN_RWSEC, qc);
+               return 0;
+       }
+
+       if (nxt_tx->ctx) {
+               EVP_CIPHER_CTX_free(nxt_tx->ctx);
+               nxt_tx->ctx = NULL;
+       }
+
+       if (!quic_tls_rx_ctx_init(&nxt_tx->ctx, tls_ctx->tx.aead, nxt_tx->key)) {
+               TRACE_DEVEL("could not initial RX TLS cipher context", QUIC_EV_CONN_RWSEC, qc);
+               return 0;
+       }
+
        return 1;
 }
 
@@ -744,34 +764,42 @@ static void quic_tls_rotate_keys(struct quic_conn *qc)
 {
        struct quic_tls_ctx *tls_ctx = &qc->els[QUIC_TLS_ENC_LEVEL_APP].tls_ctx;
        unsigned char *curr_secret, *curr_iv, *curr_key;
+       EVP_CIPHER_CTX *curr_ctx;
 
        /* Rotate the RX secrets */
+       curr_ctx = tls_ctx->rx.ctx;
        curr_secret = tls_ctx->rx.secret;
        curr_iv = tls_ctx->rx.iv;
        curr_key = tls_ctx->rx.key;
 
+       tls_ctx->rx.ctx     = qc->ku.nxt_rx.ctx;
        tls_ctx->rx.secret  = qc->ku.nxt_rx.secret;
        tls_ctx->rx.iv      = qc->ku.nxt_rx.iv;
        tls_ctx->rx.key     = qc->ku.nxt_rx.key;
 
+       qc->ku.nxt_rx.ctx    = qc->ku.prv_rx.ctx;
        qc->ku.nxt_rx.secret = qc->ku.prv_rx.secret;
        qc->ku.nxt_rx.iv     = qc->ku.prv_rx.iv;
        qc->ku.nxt_rx.key    = qc->ku.prv_rx.key;
 
+       qc->ku.prv_rx.ctx    = curr_ctx;
        qc->ku.prv_rx.secret = curr_secret;
        qc->ku.prv_rx.iv     = curr_iv;
        qc->ku.prv_rx.key    = curr_key;
        qc->ku.prv_rx.pn     = tls_ctx->rx.pn;
 
        /* Update the TX secrets */
+       curr_ctx = tls_ctx->tx.ctx;
        curr_secret = tls_ctx->tx.secret;
        curr_iv = tls_ctx->tx.iv;
        curr_key = tls_ctx->tx.key;
 
+       tls_ctx->tx.ctx    = qc->ku.nxt_tx.ctx;
        tls_ctx->tx.secret = qc->ku.nxt_tx.secret;
        tls_ctx->tx.iv     = qc->ku.nxt_tx.iv;
        tls_ctx->tx.key    = qc->ku.nxt_tx.key;
 
+       qc->ku.nxt_tx.ctx    = curr_ctx;
        qc->ku.nxt_tx.secret = curr_secret;
        qc->ku.nxt_tx.iv     = curr_iv;
        qc->ku.nxt_tx.key    = curr_key;
@@ -1342,6 +1370,7 @@ static int qc_pkt_decrypt(struct quic_rx_packet *pkt, struct quic_enc_level *qel
        int ret, kp_changed;
        unsigned char iv[QUIC_TLS_IV_LEN];
        struct quic_tls_ctx *tls_ctx = &qel->tls_ctx;
+       EVP_CIPHER_CTX *rx_ctx = tls_ctx->rx.ctx;
        unsigned char *rx_iv = tls_ctx->rx.iv;
        size_t rx_iv_sz = tls_ctx->rx.ivlen;
        unsigned char *rx_key = tls_ctx->rx.key;
@@ -1360,13 +1389,15 @@ static int qc_pkt_decrypt(struct quic_rx_packet *pkt, struct quic_enc_level *qel
                                if (!pkt->qc->ku.prv_rx.pn)
                                        return 0;
 
-                               rx_iv = pkt->qc->ku.prv_rx.iv;
+                               rx_ctx = pkt->qc->ku.prv_rx.ctx;
+                               rx_iv  = pkt->qc->ku.prv_rx.iv;
                                rx_key = pkt->qc->ku.prv_rx.key;
                        }
                        else if (pkt->pn > qel->pktns->rx.largest_pn) {
                                /* Next key phase */
                                kp_changed = 1;
-                               rx_iv = pkt->qc->ku.nxt_rx.iv;
+                               rx_ctx = pkt->qc->ku.nxt_rx.ctx;
+                               rx_iv  = pkt->qc->ku.nxt_rx.iv;
                                rx_key = pkt->qc->ku.nxt_rx.key;
                        }
                }
@@ -1377,7 +1408,7 @@ static int qc_pkt_decrypt(struct quic_rx_packet *pkt, struct quic_enc_level *qel
 
        ret = quic_tls_decrypt(pkt->data + pkt->aad_len, pkt->len - pkt->aad_len,
                               pkt->data, pkt->aad_len,
-                              tls_ctx->rx.ctx, tls_ctx->rx.aead, rx_key, iv);
+                              rx_ctx, tls_ctx->rx.aead, rx_key, iv);
        if (!ret)
                return 0;