From acd7268b61b6a7b5a8ad9c76e643b76d787c515a Mon Sep 17 00:00:00 2001 From: domienschepers Date: Thu, 10 Nov 2022 00:00:00 +0000 Subject: [PATCH] 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. [ I updated the commit message to reference the paper and the code comment to record historic behaviour as discussed in private email. ] (cherry picked from commit 61605e0ae5d8f34b89b8e71e393f3006f511e86a) --- 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 544e9c02635..110d64e869b 100644 --- a/sys/net80211/ieee80211_crypto.c +++ b/sys/net80211/ieee80211_crypto.c @@ -559,13 +559,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, @@ -577,6 +581,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; }