mirror of
https://github.com/openwrt/openwrt.git
synced 2025-01-07 14:28:50 +00:00
70 lines
2.7 KiB
Diff
70 lines
2.7 KiB
Diff
|
From: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
|
||
|
Date: Tue, 11 May 2021 20:02:42 +0200
|
||
|
Subject: [PATCH] mac80211: assure all fragments are encrypted
|
||
|
|
||
|
Do not mix plaintext and encrypted fragments in protected Wi-Fi
|
||
|
networks. This fixes CVE-2020-26147.
|
||
|
|
||
|
Previously, an attacker was able to first forward a legitimate encrypted
|
||
|
fragment towards a victim, followed by a plaintext fragment. The
|
||
|
encrypted and plaintext fragment would then be reassembled. For further
|
||
|
details see Section 6.3 and Appendix D in the paper "Fragment and Forge:
|
||
|
Breaking Wi-Fi Through Frame Aggregation and Fragmentation".
|
||
|
|
||
|
Because of this change there are now two equivalent conditions in the
|
||
|
code to determine if a received fragment requires sequential PNs, so we
|
||
|
also move this test to a separate function to make the code easier to
|
||
|
maintain.
|
||
|
|
||
|
Cc: stable@vger.kernel.org
|
||
|
Signed-off-by: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
|
||
|
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||
|
---
|
||
|
|
||
|
--- a/net/mac80211/rx.c
|
||
|
+++ b/net/mac80211/rx.c
|
||
|
@@ -2204,6 +2204,16 @@ ieee80211_reassemble_find(struct ieee802
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
+static bool requires_sequential_pn(struct ieee80211_rx_data *rx, __le16 fc)
|
||
|
+{
|
||
|
+ return rx->key &&
|
||
|
+ (rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP ||
|
||
|
+ rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256 ||
|
||
|
+ rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP ||
|
||
|
+ rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP_256) &&
|
||
|
+ ieee80211_has_protected(fc);
|
||
|
+}
|
||
|
+
|
||
|
static ieee80211_rx_result debug_noinline
|
||
|
ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
|
||
|
{
|
||
|
@@ -2248,12 +2258,7 @@ ieee80211_rx_h_defragment(struct ieee802
|
||
|
/* This is the first fragment of a new frame. */
|
||
|
entry = ieee80211_reassemble_add(rx->sdata, frag, seq,
|
||
|
rx->seqno_idx, &(rx->skb));
|
||
|
- if (rx->key &&
|
||
|
- (rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP ||
|
||
|
- rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256 ||
|
||
|
- rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP ||
|
||
|
- rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP_256) &&
|
||
|
- ieee80211_has_protected(fc)) {
|
||
|
+ if (requires_sequential_pn(rx, fc)) {
|
||
|
int queue = rx->security_idx;
|
||
|
|
||
|
/* Store CCMP/GCMP PN so that we can verify that the
|
||
|
@@ -2295,11 +2300,7 @@ ieee80211_rx_h_defragment(struct ieee802
|
||
|
u8 pn[IEEE80211_CCMP_PN_LEN], *rpn;
|
||
|
int queue;
|
||
|
|
||
|
- if (!rx->key ||
|
||
|
- (rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP &&
|
||
|
- rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP_256 &&
|
||
|
- rx->key->conf.cipher != WLAN_CIPHER_SUITE_GCMP &&
|
||
|
- rx->key->conf.cipher != WLAN_CIPHER_SUITE_GCMP_256))
|
||
|
+ if (!requires_sequential_pn(rx, fc))
|
||
|
return RX_DROP_UNUSABLE;
|
||
|
memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN);
|
||
|
for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) {
|