MINOR: quic: Add quic_tls_key_update() function for Key Update
This function derives the next RX and TX keys and IVs from secrets
for the next key update key phase. We also implement quic_tls_rotate_keys()
which rotate the key update key phase information to be able to continue
to decrypt old key phase packets. Most of these information are pointers
to unsigned char.
diff --git a/src/xprt_quic.c b/src/xprt_quic.c
index b1e48eb..f006c1a 100644
--- a/src/xprt_quic.c
+++ b/src/xprt_quic.c
@@ -675,6 +675,97 @@
TRACE_LEAVE(QUIC_EV_CONN_STIMER, ctx->conn, pktns);
}
+/* Derive new keys and ivs required for Key Update feature for <qc> QUIC
+ * connection.
+ * Return 1 if succeeded, 0 if not.
+ */
+static int quic_tls_key_update(struct quic_conn *qc)
+{
+ struct quic_tls_ctx *tls_ctx = &qc->els[QUIC_TLS_ENC_LEVEL_APP].tls_ctx;
+ struct quic_tls_secrets *rx, *tx;
+ struct quic_tls_kp *nxt_rx = &qc->ku.nxt_rx;
+ struct quic_tls_kp *nxt_tx = &qc->ku.nxt_tx;
+
+ tls_ctx = &qc->els[QUIC_TLS_ENC_LEVEL_APP].tls_ctx;
+ rx = &tls_ctx->rx;
+ tx = &tls_ctx->tx;
+ nxt_rx = &qc->ku.nxt_rx;
+ nxt_tx = &qc->ku.nxt_tx;
+
+ /* Prepare new RX secrets */
+ if (!quic_tls_sec_update(rx->md, nxt_rx->secret, nxt_rx->secretlen,
+ rx->secret, rx->secretlen)) {
+ TRACE_DEVEL("New RX secret update failed", QUIC_EV_CONN_RWSEC, qc->conn);
+ return 0;
+ }
+
+ if (!quic_tls_derive_keys(rx->aead, NULL, rx->md,
+ nxt_rx->key, nxt_rx->keylen,
+ nxt_rx->iv, nxt_rx->ivlen, NULL, 0,
+ nxt_rx->secret, nxt_rx->secretlen)) {
+ TRACE_DEVEL("New RX key derivation failed", QUIC_EV_CONN_RWSEC, qc->conn);
+ return 0;
+ }
+
+ /* Prepare new TX secrets */
+ if (!quic_tls_sec_update(tx->md, nxt_tx->secret, nxt_tx->secretlen,
+ tx->secret, tx->secretlen)) {
+ TRACE_DEVEL("New TX secret update failed", QUIC_EV_CONN_RWSEC, qc->conn);
+ return 0;
+ }
+
+ if (!quic_tls_derive_keys(tx->aead, NULL, tx->md,
+ nxt_tx->key, nxt_tx->keylen,
+ nxt_tx->iv, nxt_tx->ivlen, NULL, 0,
+ nxt_tx->secret, nxt_tx->secretlen)) {
+ TRACE_DEVEL("New TX key derivation failed", QUIC_EV_CONN_RWSEC, qc->conn);
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Rotate the Key Update information for <qc> QUIC connection.
+ * Must be used after having updated them.
+ * Always succeeds.
+ */
+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;
+
+ /* Rotate the RX secrets */
+ curr_secret = tls_ctx->rx.secret;
+ curr_iv = tls_ctx->rx.iv;
+ curr_key = tls_ctx->rx.key;
+
+ 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.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.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_secret = tls_ctx->tx.secret;
+ curr_iv = tls_ctx->tx.iv;
+ curr_key = tls_ctx->tx.key;
+
+ 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.secret = curr_secret;
+ qc->ku.nxt_tx.iv = curr_iv;
+ qc->ku.nxt_tx.key = curr_key;
+}
+
#ifndef OPENSSL_IS_BORINGSSL
int ha_quic_set_encryption_secrets(SSL *ssl, enum ssl_encryption_level_t level,
const uint8_t *read_secret,