mac80211: backport upstream fixes for FragAttacks
[openwrt/openwrt.git] / package / kernel / mac80211 / patches / subsys / 380-mac80211-assure-all-fragments-are-encrypted.patch
1 From: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
2 Date: Tue, 11 May 2021 20:02:42 +0200
3 Subject: [PATCH] mac80211: assure all fragments are encrypted
4
5 Do not mix plaintext and encrypted fragments in protected Wi-Fi
6 networks. This fixes CVE-2020-26147.
7
8 Previously, an attacker was able to first forward a legitimate encrypted
9 fragment towards a victim, followed by a plaintext fragment. The
10 encrypted and plaintext fragment would then be reassembled. For further
11 details see Section 6.3 and Appendix D in the paper "Fragment and Forge:
12 Breaking Wi-Fi Through Frame Aggregation and Fragmentation".
13
14 Because of this change there are now two equivalent conditions in the
15 code to determine if a received fragment requires sequential PNs, so we
16 also move this test to a separate function to make the code easier to
17 maintain.
18
19 Cc: stable@vger.kernel.org
20 Signed-off-by: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
21 Signed-off-by: Johannes Berg <johannes.berg@intel.com>
22 ---
23
24 --- a/net/mac80211/rx.c
25 +++ b/net/mac80211/rx.c
26 @@ -2204,6 +2204,16 @@ ieee80211_reassemble_find(struct ieee802
27 return NULL;
28 }
29
30 +static bool requires_sequential_pn(struct ieee80211_rx_data *rx, __le16 fc)
31 +{
32 + return rx->key &&
33 + (rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP ||
34 + rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256 ||
35 + rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP ||
36 + rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP_256) &&
37 + ieee80211_has_protected(fc);
38 +}
39 +
40 static ieee80211_rx_result debug_noinline
41 ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
42 {
43 @@ -2248,12 +2258,7 @@ ieee80211_rx_h_defragment(struct ieee802
44 /* This is the first fragment of a new frame. */
45 entry = ieee80211_reassemble_add(rx->sdata, frag, seq,
46 rx->seqno_idx, &(rx->skb));
47 - if (rx->key &&
48 - (rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP ||
49 - rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256 ||
50 - rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP ||
51 - rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP_256) &&
52 - ieee80211_has_protected(fc)) {
53 + if (requires_sequential_pn(rx, fc)) {
54 int queue = rx->security_idx;
55
56 /* Store CCMP/GCMP PN so that we can verify that the
57 @@ -2295,11 +2300,7 @@ ieee80211_rx_h_defragment(struct ieee802
58 u8 pn[IEEE80211_CCMP_PN_LEN], *rpn;
59 int queue;
60
61 - if (!rx->key ||
62 - (rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP &&
63 - rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP_256 &&
64 - rx->key->conf.cipher != WLAN_CIPHER_SUITE_GCMP &&
65 - rx->key->conf.cipher != WLAN_CIPHER_SUITE_GCMP_256))
66 + if (!requires_sequential_pn(rx, fc))
67 return RX_DROP_UNUSABLE;
68 memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN);
69 for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) {