* [PATCH rtw-next] wifi: rtw88: do not trust a claimed decryption
@ 2026-10-17 8:33 Luka Gejak
0 siblings, 0 replies; only message in thread
From: Luka Gejak @ 2026-10-17 8:33 UTC (permalink / raw)
To: Ping-Ke Shih
Cc: Bob Beckett, linux-wireless, kernel, matthew.leach, Luka Gejak
The RX descriptor says how the CRC and ICV checks on the device's own copy
of the frame went, not that the bytes in our buffer are that frame. For a
frame that is marked decrypted mac80211 reads the PN out of the CCMP header
and stores it as the key's last PN, rejecting only a lower PN, so a single
frame with a garbage CCMP header makes every genuine frame after it be
dropped as a replay.
Only claim decryption for a frame that passed the CRC and ICV checks, and
only for an AES frame whose CCMP or GCMP header is well formed. Such a
frame is left to mac80211, which drops it without moving the replay
counter. Mark a frame that failed the ICV with RX_FLAG_FAILED_FCS_CRC,
the way rtw89 does.
Reported-by: Bob Beckett <bob.beckett@collabora.com>
Closes: https://lore.kernel.org/all/20261016191100.1781056-1-bob.beckett@collabora.com/
Signed-off-by: Luka Gejak <luka.gejak@linux.dev>
---
drivers/net/wireless/realtek/rtw88/rx.c | 30 +++++++++++++++++++++++--
1 file changed, 28 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw88/rx.c b/drivers/net/wireless/realtek/rtw88/rx.c
index fde21c840ac0..45ff18fa8c7b 100644
--- a/drivers/net/wireless/realtek/rtw88/rx.c
+++ b/drivers/net/wireless/realtek/rtw88/rx.c
@@ -208,7 +208,7 @@ static void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev,
if (rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_SCAN_OFFLOAD) &&
test_bit(RTW_FLAG_SCANNING, rtwdev->flags))
rtw_set_rx_freq_by_pktstat(pkt_stat, rx_status);
- if (pkt_stat->crc_err)
+ if (pkt_stat->crc_err || pkt_stat->icv_err)
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
if (pkt_stat->decrypted)
rx_status->flag |= RX_FLAG_DECRYPTED;
@@ -264,6 +264,24 @@ static void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev,
}
}
+static bool rtw_rx_ccmp_hdr_valid(struct rtw_rx_pkt_stat *pkt_stat,
+ struct ieee80211_hdr *hdr)
+{
+ u32 hdr_len = ieee80211_hdrlen(hdr->frame_control);
+ u8 *iv;
+
+ if (!ieee80211_has_protected(hdr->frame_control))
+ return true;
+
+ if (pkt_stat->pkt_len < hdr_len + IEEE80211_CCMP_HDR_LEN + FCS_LEN)
+ return false;
+
+ iv = (u8 *)hdr + hdr_len;
+
+ /* reserved octet is zero, key ID octet has ExtIV set */
+ return iv[2] == 0 && (iv[3] & BIT(5));
+}
+
int rtw_rx_query_rx_desc(struct rtw_dev *rtwdev, void *rx_desc8,
struct rtw_rx_pkt_stat *pkt_stat,
struct ieee80211_rx_status *rx_status)
@@ -285,7 +303,8 @@ int rtw_rx_query_rx_desc(struct rtw_dev *rtwdev, void *rx_desc8,
pkt_stat->shift = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_SHIFT);
pkt_stat->phy_status = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_PHYST);
swdec = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_SWDEC);
- pkt_stat->decrypted = !swdec && enc_type != RX_DESC_ENC_NONE;
+ pkt_stat->decrypted = !swdec && enc_type != RX_DESC_ENC_NONE &&
+ !pkt_stat->crc_err && !pkt_stat->icv_err;
pkt_stat->cam_id = le32_get_bits(rx_desc->w1, RTW_RX_DESC_W1_MACID);
@@ -328,6 +347,13 @@ int rtw_rx_query_rx_desc(struct rtw_dev *rtwdev, void *rx_desc8,
if (pkt_stat->phy_status)
rtwdev->chip->ops->query_phy_status(rtwdev, phy_status, pkt_stat);
+ if (pkt_stat->decrypted && enc_type == RX_DESC_ENC_AES &&
+ !rtw_rx_ccmp_hdr_valid(pkt_stat, hdr)) {
+ rtw_dbg(rtwdev, RTW_DBG_RX,
+ "AES frame without a usable CCMP header, drop the decryption flag\n");
+ pkt_stat->decrypted = false;
+ }
+
rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status);
return 0;
--
2.53.0
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-10-17 8:33 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-17 8:33 [PATCH rtw-next] wifi: rtw88: do not trust a claimed decryption Luka Gejak
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox