git: e020f9602809 - releng/12.4 - net80211: fail for unicast traffic without unicast key

From: Gordon Tetlow <gordon_at_FreeBSD.org>
Date: Wed, 06 Sep 2023 17:37:45 UTC
The branch releng/12.4 has been updated by gordon:

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

commit e020f9602809e6973b189d6d30e325f1f92f7148
Author:     domienschepers <schepers.d@northeastern.edu>
AuthorDate: 2022-11-10 00:00:00 +0000
Commit:     Gordon Tetlow <gordon@FreeBSD.org>
CommitDate: 2023-09-06 17:20:03 +0000

    net80211: fail for unicast traffic without unicast key
    
    Falling back to the multicast key may cause unicast traffic to leak.
    Instead fail when no key is found.
    
    For more information see the 'Framing Frames: Bypassing Wi-Fi Encryption
    by Manipulating Transmit Queues' paper.
    
    Approved by:    so
    Security:       FreeBSD-SA-23:11.wifi
    Security:       CVE-2022-47522
    
    (cherry picked from commit 61605e0ae5d8f34b89b8e71e393f3006f511e86a)
    (cherry picked from commit 84d538470bced9b1a45064c7845c92551a15e3e1)
---
 sys/net80211/ieee80211_crypto.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/sys/net80211/ieee80211_crypto.c b/sys/net80211/ieee80211_crypto.c
index d565b3511170..0e605bf13a43 100644
--- a/sys/net80211/ieee80211_crypto.c
+++ b/sys/net80211/ieee80211_crypto.c
@@ -560,13 +560,17 @@ ieee80211_crypto_get_txkey(struct ieee80211_node *ni, struct mbuf *m)
 
 	/*
 	 * Multicast traffic always uses the multicast key.
-	 * Otherwise if a unicast key is set we use that and
-	 * it is always key index 0.  When no unicast key is
-	 * set we fall back to the default transmit key.
+	 *
+	 * Historically we would fall back to the default
+	 * transmit key if there was no unicast key.  This
+	 * behaviour was documented up to IEEE Std 802.11-2016,
+	 * 12.9.2.2 Per-MSDU/Per-A-MSDU Tx pseudocode, in the
+	 * 'else' case but is no longer in later versions of
+	 * the standard.  Additionally falling back to the
+	 * group key for unicast was a security risk.
 	 */
 	wh = mtod(m, struct ieee80211_frame *);
-	if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
-	    IEEE80211_KEY_UNDEFINED(&ni->ni_ucastkey)) {
+	if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
 		if (vap->iv_def_txkey == IEEE80211_KEYIX_NONE) {
 			IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO,
 			    wh->i_addr1,
@@ -578,6 +582,8 @@ ieee80211_crypto_get_txkey(struct ieee80211_node *ni, struct mbuf *m)
 		return &vap->iv_nw_keys[vap->iv_def_txkey];
 	}
 
+	if (IEEE80211_KEY_UNDEFINED(&ni->ni_ucastkey))
+		return NULL;
 	return &ni->ni_ucastkey;
 }