The branch stable/14 has been updated by bz:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=bdc94f09bd96b28dcb841afa31f44b0879130134

commit bdc94f09bd96b28dcb841afa31f44b0879130134
Author:     Bjoern A. Zeeb <b...@freebsd.org>
AuthorDate: 2025-01-07 12:02:54 +0000
Commit:     Bjoern A. Zeeb <b...@freebsd.org>
CommitDate: 2025-02-24 20:26:48 +0000

    net80211/crypto: LinuxKPI/802.11: introduce IEEE80211_RX_F_PN_VALIDATED
    
    There are cases when we see "rx seq# violation (CCMP)".
    
    Historically these were AHDEMO/IBBS cases (IEEE80211_KEY_NOREPLAY,
    see 5d766a09daab2).
    
    With iwlwifi(4) doing RSS for newer chipsets and us not having any idea
    about multiple rx-queues (passed all the way through) leads to the same
    problem.  An easy way to trigger this is doing an IPv6 all-nodes echo
    request.  With a sufficient amount of nodes answering the answers will
    be hashed to different queues and re-ordering will likely take place
    as queues get released individually.
    However crypto validation is already done in fw/driver for these cases
    and we need to carry the state forward.  Add IEEE80211_RX_F_PN_VALIDATED
    to indicate that the checks were done passing the information from driver
    through LinuxKPI to net80211.
    LinuxKPI enforces that a frame was indeed decrypted; otherwise the flag
    would be invalid.
    
    This also avoids returning an error and no key from
    ieee80211_crypto_decap() and thus avoids dropping the frame.
    
    Sponsored by:   The FreeBSD Foundation
    Reviewed by:    adrian
    Differential Revision: https://reviews.freebsd.org/D49029
    
    (cherry picked from commit ec6185c52661d3af0dac6dcc8701fc49fae3e1d9)
---
 sys/compat/linuxkpi/common/src/linux_80211.c | 16 +++++++++++++++-
 sys/net80211/_ieee80211.h                    |  1 +
 sys/net80211/ieee80211_crypto_ccmp.c         | 16 +++++++++++++---
 3 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c 
b/sys/compat/linuxkpi/common/src/linux_80211.c
index 02cacc62a4c2..7b0ddc3cbf9a 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211.c
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2020-2024 The FreeBSD Foundation
+ * Copyright (c) 2020-2025 The FreeBSD Foundation
  * Copyright (c) 2020-2025 Bjoern A. Zeeb
  *
  * This software was developed by Björn Zeeb under sponsorship from
@@ -5425,6 +5425,20 @@ no_trace_beacons:
        rx_stats.c_freq = rx_status->freq;
        rx_stats.c_ieee = ieee80211_mhz2ieee(rx_stats.c_freq, rx_stats.c_band);
 
+       /*
+        * We only need these for LKPI_80211_HW_CRYPTO in theory but in
+        * case the hardware does something we do not expect always leave
+        * these enabled.  Leaving this commant as documentation for the || 1.
+        */
+#if defined(LKPI_80211_HW_CRYPTO) || 1
+       if (rx_status->flag & RX_FLAG_DECRYPTED) {
+               rx_stats.c_pktflags |= IEEE80211_RX_F_DECRYPTED;
+               /* Only valid if decrypted is set. */
+               if (rx_status->flag & RX_FLAG_PN_VALIDATED)
+                       rx_stats.c_pktflags |= IEEE80211_RX_F_PN_VALIDATED;
+       }
+#endif
+
        /* XXX (*sta_statistics)() to get to some of that? */
        /* XXX-BZ dump the FreeBSD version of rx_stats as well! */
 
diff --git a/sys/net80211/_ieee80211.h b/sys/net80211/_ieee80211.h
index 929de475f4bf..8b86cd612168 100644
--- a/sys/net80211/_ieee80211.h
+++ b/sys/net80211/_ieee80211.h
@@ -573,6 +573,7 @@ struct ieee80211_mimo_info {
 #define        IEEE80211_RX_F_OFDM             0x00002000
 #define        IEEE80211_RX_F_HT               0x00004000
 #define        IEEE80211_RX_F_VHT              0x00008000
+#define        IEEE80211_RX_F_PN_VALIDATED     0x00010000 /* Decrypted; PN 
validated */
 
 /* Channel width */
 #define        IEEE80211_RX_FW_20MHZ           1
diff --git a/sys/net80211/ieee80211_crypto_ccmp.c 
b/sys/net80211/ieee80211_crypto_ccmp.c
index 45e795a8799b..8f7d5eed593c 100644
--- a/sys/net80211/ieee80211_crypto_ccmp.c
+++ b/sys/net80211/ieee80211_crypto_ccmp.c
@@ -238,6 +238,7 @@ ccmp_decap(struct ieee80211_key *k, struct mbuf *m, int 
hdrlen)
        struct ieee80211_frame *wh;
        uint8_t *ivp, tid;
        uint64_t pn;
+       bool noreplaycheck;
 
        rxs = ieee80211_get_rx_params_ptr(m);
 
@@ -261,8 +262,10 @@ ccmp_decap(struct ieee80211_key *k, struct mbuf *m, int 
hdrlen)
        }
        tid = ieee80211_gettid(wh);
        pn = READ_6(ivp[0], ivp[1], ivp[4], ivp[5], ivp[6], ivp[7]);
-       if (pn <= k->wk_keyrsc[tid] &&
-           (k->wk_flags & IEEE80211_KEY_NOREPLAY) == 0) {
+
+       noreplaycheck = (k->wk_flags & IEEE80211_KEY_NOREPLAY) != 0;
+       noreplaycheck |= (rxs != NULL) && (rxs->c_pktflags & 
IEEE80211_RX_F_PN_VALIDATED) != 0;
+       if (pn <= k->wk_keyrsc[tid] && !noreplaycheck) {
                /*
                 * Replay violation.
                 */
@@ -302,7 +305,14 @@ finish:
         * Ok to update rsc now.
         */
        if (! ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP))) {
-               k->wk_keyrsc[tid] = pn;
+               /*
+                * Do not go backwards in the IEEE80211_KEY_NOREPLAY cases
+                * or in case hardware has checked but frames are arriving
+                * reordered (e.g., LinuxKPI drivers doing RSS which we are
+                * not prepared for at all).
+                */
+               if (pn > k->wk_keyrsc[tid])
+                       k->wk_keyrsc[tid] = pn;
        }
 
        return 1;

Reply via email to