de0f89a5b0446f2f7a373c1be2a0aa49911846f8
[openwrt/openwrt.git] /
1 From: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
2 Date: Tue, 11 May 2021 20:02:43 +0200
3 Subject: [PATCH] mac80211: prevent mixed key and fragment cache attacks
4
5 Simultaneously prevent mixed key attacks (CVE-2020-24587) and fragment
6 cache attacks (CVE-2020-24586). This is accomplished by assigning a
7 unique color to every key (per interface) and using this to track which
8 key was used to decrypt a fragment. When reassembling frames, it is
9 now checked whether all fragments were decrypted using the same key.
10
11 To assure that fragment cache attacks are also prevented, the ID that is
12 assigned to keys is unique even over (re)associations and (re)connects.
13 This means fragments separated by a (re)association or (re)connect will
14 not be reassembled. Because mac80211 now also prevents the reassembly of
15 mixed encrypted and plaintext fragments, all cache attacks are prevented.
16
17 Cc: stable@vger.kernel.org
18 Signed-off-by: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
19 Signed-off-by: Johannes Berg <johannes.berg@intel.com>
20 ---
21
22 --- a/net/mac80211/ieee80211_i.h
23 +++ b/net/mac80211/ieee80211_i.h
24 @@ -97,6 +97,7 @@ struct ieee80211_fragment_entry {
25 u8 rx_queue;
26 bool check_sequential_pn; /* needed for CCMP/GCMP */
27 u8 last_pn[6]; /* PN of the last fragment if CCMP was used */
28 + unsigned int key_color;
29 };
30
31
32 --- a/net/mac80211/key.c
33 +++ b/net/mac80211/key.c
34 @@ -799,6 +799,7 @@ int ieee80211_key_link(struct ieee80211_
35 struct ieee80211_sub_if_data *sdata,
36 struct sta_info *sta)
37 {
38 + static atomic_t key_color = ATOMIC_INIT(0);
39 struct ieee80211_key *old_key;
40 int idx = key->conf.keyidx;
41 bool pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE;
42 @@ -850,6 +851,12 @@ int ieee80211_key_link(struct ieee80211_
43 key->sdata = sdata;
44 key->sta = sta;
45
46 + /*
47 + * Assign a unique ID to every key so we can easily prevent mixed
48 + * key and fragment cache attacks.
49 + */
50 + key->color = atomic_inc_return(&key_color);
51 +
52 increment_tailroom_need_count(sdata);
53
54 ret = ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
55 --- a/net/mac80211/key.h
56 +++ b/net/mac80211/key.h
57 @@ -128,6 +128,8 @@ struct ieee80211_key {
58 } debugfs;
59 #endif
60
61 + unsigned int color;
62 +
63 /*
64 * key config, must be last because it contains key
65 * material as variable length member
66 --- a/net/mac80211/rx.c
67 +++ b/net/mac80211/rx.c
68 @@ -2265,6 +2265,7 @@ ieee80211_rx_h_defragment(struct ieee802
69 * next fragment has a sequential PN value.
70 */
71 entry->check_sequential_pn = true;
72 + entry->key_color = rx->key->color;
73 memcpy(entry->last_pn,
74 rx->key->u.ccmp.rx_pn[queue],
75 IEEE80211_CCMP_PN_LEN);
76 @@ -2302,6 +2303,11 @@ ieee80211_rx_h_defragment(struct ieee802
77
78 if (!requires_sequential_pn(rx, fc))
79 return RX_DROP_UNUSABLE;
80 +
81 + /* Prevent mixed key and fragment cache attacks */
82 + if (entry->key_color != rx->key->color)
83 + return RX_DROP_UNUSABLE;
84 +
85 memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN);
86 for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) {
87 pn[i]++;