QUIC CHANNEL: Enforce the RX packet forgery limit
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)

ssl/quic/quic_channel.c

index 951160a7f07886df7bba94f0bf8f7b8779f5f2b8..386da88d02ea1fc8de232329b40d7d464b69c6bf 100644 (file)
@@ -1641,6 +1641,38 @@ static void ch_rx_pre(QUIC_CHANNEL *ch)
         ch_raise_net_error(ch);
 }
 
+/* Check incoming forged packet limit and terminate connection if needed. */
+static void ch_rx_check_forged_pkt_limit(QUIC_CHANNEL *ch)
+{
+    uint32_t enc_level;
+    uint64_t limit = UINT64_MAX, l;
+
+    for (enc_level = QUIC_ENC_LEVEL_INITIAL;
+         enc_level < QUIC_ENC_LEVEL_NUM;
+         ++enc_level)
+    {
+        /*
+         * Different ELs can have different AEADs which can in turn impose
+         * different limits, so use the lowest value of any currently valid EL.
+         */
+        if ((ch->el_discarded & (1U << enc_level)) != 0)
+            continue;
+
+        if (enc_level > ch->rx_enc_level)
+            break;
+
+        l = ossl_qrx_get_max_forged_pkt_count(ch->qrx, enc_level);
+        if (l < limit)
+            limit = l;
+    }
+
+    if (ossl_qrx_get_cur_forged_pkt_count(ch->qrx) < limit)
+        return;
+
+    ossl_quic_channel_raise_protocol_error(ch, QUIC_ERR_AEAD_LIMIT_REACHED, 0,
+                                           "forgery limit");
+}
+
 /* Process queued incoming packets and handle frames, if any. */
 static int ch_rx(QUIC_CHANNEL *ch)
 {
@@ -1676,6 +1708,8 @@ static int ch_rx(QUIC_CHANNEL *ch)
         handled_any = 1;
     }
 
+    ch_rx_check_forged_pkt_limit(ch);
+
     /*
      * When in TERMINATING - CLOSING, generate a CONN_CLOSE frame whenever we
      * process one or more incoming packets.