]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
QUIC QRX: Don't process 1-RTT packets until handshake is complete
authorHugo Landau <hlandau@openssl.org>
Tue, 25 Jul 2023 10:32:25 +0000 (11:32 +0100)
committerMatt Caswell <matt@openssl.org>
Tue, 8 Aug 2023 13:33:42 +0000 (14:33 +0100)
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/21547)

include/internal/quic_record_rx.h
ssl/quic/quic_channel.c
ssl/quic/quic_record_rx.c
test/quic_record_test.c

index 19545c3e3a107aa334cdb95fbf308e4d2a3172a6..ed5cdefb2f9871608a4b971d43e204765f9b8371 100644 (file)
@@ -338,6 +338,17 @@ int ossl_qrx_set_late_validation_cb(OSSL_QRX *qrx,
  */
 void ossl_qrx_inject_urxe(OSSL_QRX *qrx, QUIC_URXE *e);
 
+/*
+ * Decryption of 1-RTT packets must be explicitly enabled by calling this
+ * function. This is to comply with the requirement that we not process 1-RTT
+ * packets until the handshake is complete, even if we already have 1-RTT
+ * secrets. Even if a 1-RTT secret is provisioned for the QRX, incoming 1-RTT
+ * packets will be handled as though no key is available until this function is
+ * called. Calling this function will then requeue any such deferred packets for
+ * processing.
+ */
+void ossl_qrx_allow_1rtt_processing(OSSL_QRX *qrx);
+
 /*
  * Key Update (RX)
  * ===============
index fa9866bdde23e518e1dd51f2a7737ec27edd67f1..615fef48a45c2b13e3b10e78d372cd80f11dca6e 100644 (file)
@@ -951,6 +951,9 @@ static int ch_on_handshake_complete(void *arg)
     OPENSSL_free(ch->local_transport_params);
     ch->local_transport_params = NULL;
 
+    /* Tell the QRX it can now process 1-RTT packets. */
+    ossl_qrx_allow_1rtt_processing(ch->qrx);
+
     /* Tell TXP the handshake is complete. */
     ossl_quic_tx_packetiser_notify_handshake_complete(ch->txp);
 
index 74693900cff5ee36b02e8724573ee670aa9fa0d3..feb32d92725126dbc65710f5b952c78952322607 100644 (file)
@@ -158,6 +158,9 @@ struct ossl_qrx_st {
     /* Initial key phase. For debugging use only; always 0 in real use. */
     unsigned char                   init_key_phase_bit;
 
+    /* Are we allowed to process 1-RTT packets yet? */
+    unsigned char                   allow_1rtt;
+
     /* Message callback related arguments */
     ossl_msg_cb msg_callback;
     void *msg_callback_arg;
@@ -883,6 +886,13 @@ static int qrx_process_pkt(OSSL_QRX *qrx, QUIC_URXE *urxe,
     switch (ossl_qrl_enc_level_set_have_el(&qrx->el_set, enc_level)) {
         case 1:
             /* We have keys. */
+            if (enc_level == QUIC_ENC_LEVEL_1RTT && !qrx->allow_1rtt)
+                /*
+                 * But we cannot process 1-RTT packets until the handshake is
+                 * completed (RFC 9000 s. 5.7).
+                 */
+                goto cannot_decrypt;
+
             break;
         case 0:
             /* No keys yet. */
@@ -1314,6 +1324,15 @@ uint64_t ossl_qrx_get_max_forged_pkt_count(OSSL_QRX *qrx,
         : ossl_qrl_get_suite_max_forged_pkt(el->suite_id);
 }
 
+void ossl_qrx_allow_1rtt_processing(OSSL_QRX *qrx)
+{
+    if (qrx->allow_1rtt)
+        return;
+
+    qrx->allow_1rtt = 1;
+    qrx_requeue_deferred(qrx);
+}
+
 void ossl_qrx_set_msg_callback(OSSL_QRX *qrx, ossl_msg_cb msg_callback,
                                SSL *msg_callback_ssl)
 {
index d2b18882c5b06f917fd6000f8624be67a1518792..ef0aa9bd623a7f3c1303455c4bddb6ed7fbc39bb 100644 (file)
@@ -1744,6 +1744,7 @@ static int rx_state_ensure(struct rx_state *s)
         && !TEST_ptr(s->qrx = ossl_qrx_new(&s->args)))
         return 0;
 
+    ossl_qrx_allow_1rtt_processing(s->qrx);
     return 1;
 }