git: a2d087b67e14 - main - net80211: fix CCMP/GCMP AAD for MFP frames

From: Adrian Chadd <adrian_at_FreeBSD.org>
Date: Wed, 01 Jul 2026 00:18:48 UTC
The branch main has been updated by adrian:

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

commit a2d087b67e14ea2a2496d6424df8d9668e271177
Author:     Adrian Chadd <adrian@FreeBSD.org>
AuthorDate: 2026-07-01 00:18:00 +0000
Commit:     Adrian Chadd <adrian@FreeBSD.org>
CommitDate: 2026-07-01 00:18:40 +0000

    net80211: fix CCMP/GCMP AAD for MFP frames
    
    Update ieee80211_crypto_init_aad() to do what 802.11-2020 says -
    only mask fc[0] bits 4-6 on data frames, not on management frames.
    This (with other diffs to actually negotiate MFP and configure
    ath(4) for MFP + software keys) allows the CCMP path to decrypt
    CCMP MFP frames in the software path.
    
    Differential Revision:  https://reviews.freebsd.org/D57799
---
 sys/net80211/ieee80211_crypto.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/sys/net80211/ieee80211_crypto.c b/sys/net80211/ieee80211_crypto.c
index 566f0b2e0c23..3dad4ce77d3c 100644
--- a/sys/net80211/ieee80211_crypto.c
+++ b/sys/net80211/ieee80211_crypto.c
@@ -1025,7 +1025,8 @@ ieee80211_crypto_init_aad(const struct ieee80211_frame *wh, uint8_t *aad,
 	/*
 	 * AAD for PV0 MPDUs:
 	 *
-	 * FC with bits 4..6 and 11..13 masked to zero; 14 is always one
+	 * FC + data frame - mask bits 4..6
+	 * FC 11..13 masked to zero; 14 is always one
 	 * A1 | A2 | A3
 	 * SC with bits 4..15 (seq#) masked to zero
 	 * A4 (if present)
@@ -1033,7 +1034,11 @@ ieee80211_crypto_init_aad(const struct ieee80211_frame *wh, uint8_t *aad,
 	 */
 	aad[0] = 0;	/* AAD length >> 8 */
 	/* NB: aad[1] set below */
-	aad[2] = wh->i_fc[0] & 0x8f;	/* see above for bitfields */
+	/* Only mask bits 4,5,6 if its a data frame */
+	aad[2] = wh->i_fc[0];
+	if (IEEE80211_IS_DATA(wh))
+		aad[2] &= 0x8f; /* see above for bitfields */
+
 	aad[3] = wh->i_fc[1] & 0xc7;	/* see above for bitfields */
 	/* mask aad[3] b7 if frame is data frame w/ QoS control field */
 	if (IEEE80211_IS_QOS_ANY(wh))