QUIC: Add internal APIs for white-box testing of key update
authorHugo Landau <hlandau@openssl.org>
Tue, 23 May 2023 11:23:06 +0000 (12:23 +0100)
committerPauli <pauli@openssl.org>
Thu, 15 Jun 2023 23:26:28 +0000 (09:26 +1000)
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/21029)

include/internal/quic_channel.h
include/internal/quic_record_tx.h
include/internal/quic_ssl.h
ssl/quic/quic_channel.c
ssl/quic/quic_channel_local.h
ssl/quic/quic_impl.c
ssl/quic/quic_record_tx.c

index 25b6758d8d14e11f5dd4b922350e40e2a2cc6d4f..99e3dd6c76eb423ce33d5a14c57c550dfc643202 100644 (file)
@@ -330,6 +330,14 @@ void ossl_quic_channel_set_msg_callback(QUIC_CHANNEL *ch,
 void ossl_quic_channel_set_msg_callback_arg(QUIC_CHANNEL *ch,
                                             void *msg_callback_arg);
 
+/* Testing use only - sets a TXKU threshold packet count override value. */
+void ossl_quic_channel_set_txku_threshold_override(QUIC_CHANNEL *ch,
+                                                   uint64_t tx_pkt_threshold);
+
+/* Testing use only - gets current 1-RTT key epochs for QTX and QRX. */
+uint64_t ossl_quic_channel_get_tx_key_epoch(QUIC_CHANNEL *ch);
+uint64_t ossl_quic_channel_get_rx_key_epoch(QUIC_CHANNEL *ch);
+
 # endif
 
 #endif
index 8b4e1705cb8cae80a39951a106d8ef563378b6ca..b4c9bb8d26774ac5b559a96b146d1d041331a5ce 100644 (file)
@@ -362,6 +362,12 @@ uint64_t ossl_qtx_get_cur_epoch_pkt_count(OSSL_QTX *qtx, uint32_t enc_level);
  */
 uint64_t ossl_qtx_get_max_epoch_pkt_count(OSSL_QTX *qtx, uint32_t enc_level);
 
+/*
+ * Get the 1-RTT EL key epoch number for the QTX. This is intended for
+ * diagnostic purposes. Returns 0 if 1-RTT EL is not provisioned yet.
+ */
+uint64_t ossl_qtx_get_key_epoch(OSSL_QTX *qtx);
+
 # endif
 
 #endif
index 7ea5ce8063229c68a49b3a5526264bcf1a068c81..ed69a8005797ae4c126ab84989eb32606ecabb95 100644 (file)
@@ -14,6 +14,7 @@
 # include <openssl/bio.h>
 # include "internal/quic_record_rx.h" /* OSSL_QRX */
 # include "internal/quic_ackm.h"      /* OSSL_ACKM */
+# include "internal/quic_channel.h"   /* QUIC_CHANNEL */
 
 # ifndef OPENSSL_NO_QUIC
 
@@ -108,6 +109,9 @@ int ossl_quic_conn_set_override_now_cb(SSL *s,
  */
 void ossl_quic_conn_force_assist_thread_wake(SSL *s);
 
+/* For use by tests only. */
+QUIC_CHANNEL *ossl_quic_conn_get_channel(SSL *s);
+
 # endif
 
 #endif
index 386da88d02ea1fc8de232329b40d7d464b69c6bf..c4dfa58bc14be07d1b019063d03cf6555257e4a8 100644 (file)
@@ -296,6 +296,7 @@ static int ch_init(QUIC_CHANNEL *ch)
     ch->max_idle_timeout        = QUIC_DEFAULT_IDLE_TIMEOUT;
     ch->tx_enc_level            = QUIC_ENC_LEVEL_INITIAL;
     ch->rx_enc_level            = QUIC_ENC_LEVEL_INITIAL;
+    ch->txku_threshold_override = UINT64_MAX;
 
     /*
      * Determine the QUIC Transport Parameters and serialize the transport
@@ -595,14 +596,18 @@ static int txku_recommendable(QUIC_CHANNEL *ch)
 QUIC_NEEDS_LOCK
 static int txku_desirable(QUIC_CHANNEL *ch)
 {
-    uint64_t cur_pkt_count, max_pkt_count;
+    uint64_t cur_pkt_count, max_pkt_count, thresh_pkt_count;
     const uint32_t enc_level = QUIC_ENC_LEVEL_1RTT;
 
     /* Check AEAD limit to determine if we should perform a spontaneous TXKU. */
     cur_pkt_count = ossl_qtx_get_cur_epoch_pkt_count(ch->qtx, enc_level);
     max_pkt_count = ossl_qtx_get_max_epoch_pkt_count(ch->qtx, enc_level);
 
-    return cur_pkt_count >= max_pkt_count / 2;
+    thresh_pkt_count = max_pkt_count / 2;
+    if (ch->txku_threshold_override != UINT64_MAX)
+        thresh_pkt_count = ch->txku_threshold_override;
+
+    return cur_pkt_count >= thresh_pkt_count;
 }
 
 QUIC_NEEDS_LOCK
@@ -2858,3 +2863,19 @@ void ossl_quic_channel_set_msg_callback_arg(QUIC_CHANNEL *ch,
     ossl_quic_tx_packetiser_set_msg_callback_arg(ch->txp, msg_callback_arg);
     ossl_qrx_set_msg_callback_arg(ch->qrx, msg_callback_arg);
 }
+
+void ossl_quic_channel_set_txku_threshold_override(QUIC_CHANNEL *ch,
+                                                   uint64_t tx_pkt_threshold)
+{
+    ch->txku_threshold_override = tx_pkt_threshold;
+}
+
+uint64_t ossl_quic_channel_get_tx_key_epoch(QUIC_CHANNEL *ch)
+{
+    return ossl_qtx_get_key_epoch(ch->qtx);
+}
+
+uint64_t ossl_quic_channel_get_rx_key_epoch(QUIC_CHANNEL *ch)
+{
+    return ossl_qrx_get_key_epoch(ch->qrx);
+}
index 607f109119d419b27a85db559d6b10904a8c90c9..f2c84c450c4ec18d255c0e268dcedf6e5455bc07 100644 (file)
@@ -193,6 +193,14 @@ struct quic_channel_st {
      */
     uint64_t                        incoming_stream_auto_reject_aec;
 
+    /*
+     * Override packet count threshold at which we do a spontaneous TXKU.
+     * Usually UINT64_MAX in which case a suitable value is chosen based on AEAD
+     * limit advice from the QRL utility functions. This is intended for testing
+     * use only. Usually set to UINT64_MAX.
+     */
+    uint64_t                        txku_threshold_override;
+
     /* Valid if we are in the TERMINATING or TERMINATED states. */
     QUIC_TERMINATE_CAUSE            terminate_cause;
 
index 9cfc253bdccf5870aec47c2a54f1826279e665e3..548fcbc89e502243db9ace58d577516cc872e6d1 100644 (file)
@@ -2746,3 +2746,18 @@ const SSL_CIPHER *ossl_quic_get_cipher(unsigned int u)
 {
     return NULL;
 }
+
+/*
+ * Internal Testing APIs
+ * =====================
+ */
+
+QUIC_CHANNEL *ossl_quic_conn_get_channel(SSL *s)
+{
+    QCTX ctx;
+
+    if (!expect_quic_conn_only(s, &ctx))
+        return NULL;
+
+    return ctx.qc->ch;
+}
index 69a5ebea54b1ed714f8163bb9fcadcae7311363f..243f8a4dd8652eb551498c1f738a57072ca7a25c 100644 (file)
@@ -1014,3 +1014,14 @@ void ossl_qtx_set_msg_callback_arg(OSSL_QTX *qtx, void *msg_callback_arg)
 {
     qtx->msg_callback_arg = msg_callback_arg;
 }
+
+uint64_t ossl_qtx_get_key_epoch(OSSL_QTX *qtx)
+{
+    OSSL_QRL_ENC_LEVEL *el;
+
+    el = ossl_qrl_enc_level_set_get(&qtx->el_set, QUIC_ENC_LEVEL_1RTT, 1);
+    if (el == NULL)
+        return 0;
+
+    return el->key_epoch;
+}