mac80211: backport upstream fixes for FragAttacks
[openwrt/openwrt.git] / package / kernel / mac80211 / patches / subsys / 381-mac80211-prevent-mixed-key-and-fragment-cache-attack.patch
diff --git a/package/kernel/mac80211/patches/subsys/381-mac80211-prevent-mixed-key-and-fragment-cache-attack.patch b/package/kernel/mac80211/patches/subsys/381-mac80211-prevent-mixed-key-and-fragment-cache-attack.patch
new file mode 100644 (file)
index 0000000..de0f89a
--- /dev/null
@@ -0,0 +1,87 @@
+From: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
+Date: Tue, 11 May 2021 20:02:43 +0200
+Subject: [PATCH] mac80211: prevent mixed key and fragment cache attacks
+
+Simultaneously prevent mixed key attacks (CVE-2020-24587) and fragment
+cache attacks (CVE-2020-24586). This is accomplished by assigning a
+unique color to every key (per interface) and using this to track which
+key was used to decrypt a fragment. When reassembling frames, it is
+now checked whether all fragments were decrypted using the same key.
+
+To assure that fragment cache attacks are also prevented, the ID that is
+assigned to keys is unique even over (re)associations and (re)connects.
+This means fragments separated by a (re)association or (re)connect will
+not be reassembled. Because mac80211 now also prevents the reassembly of
+mixed encrypted and plaintext fragments, all cache attacks are prevented.
+
+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/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -97,6 +97,7 @@ struct ieee80211_fragment_entry {
+       u8 rx_queue;
+       bool check_sequential_pn; /* needed for CCMP/GCMP */
+       u8 last_pn[6]; /* PN of the last fragment if CCMP was used */
++      unsigned int key_color;
+ };
+--- a/net/mac80211/key.c
++++ b/net/mac80211/key.c
+@@ -799,6 +799,7 @@ int ieee80211_key_link(struct ieee80211_
+                      struct ieee80211_sub_if_data *sdata,
+                      struct sta_info *sta)
+ {
++      static atomic_t key_color = ATOMIC_INIT(0);
+       struct ieee80211_key *old_key;
+       int idx = key->conf.keyidx;
+       bool pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE;
+@@ -850,6 +851,12 @@ int ieee80211_key_link(struct ieee80211_
+       key->sdata = sdata;
+       key->sta = sta;
++      /*
++       * Assign a unique ID to every key so we can easily prevent mixed
++       * key and fragment cache attacks.
++       */
++      key->color = atomic_inc_return(&key_color);
++
+       increment_tailroom_need_count(sdata);
+       ret = ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
+--- a/net/mac80211/key.h
++++ b/net/mac80211/key.h
+@@ -128,6 +128,8 @@ struct ieee80211_key {
+       } debugfs;
+ #endif
++      unsigned int color;
++
+       /*
+        * key config, must be last because it contains key
+        * material as variable length member
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -2265,6 +2265,7 @@ ieee80211_rx_h_defragment(struct ieee802
+                        * next fragment has a sequential PN value.
+                        */
+                       entry->check_sequential_pn = true;
++                      entry->key_color = rx->key->color;
+                       memcpy(entry->last_pn,
+                              rx->key->u.ccmp.rx_pn[queue],
+                              IEEE80211_CCMP_PN_LEN);
+@@ -2302,6 +2303,11 @@ ieee80211_rx_h_defragment(struct ieee802
+               if (!requires_sequential_pn(rx, fc))
+                       return RX_DROP_UNUSABLE;
++
++              /* Prevent mixed key and fragment cache attacks */
++              if (entry->key_color != rx->key->color)
++                      return RX_DROP_UNUSABLE;
++
+               memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN);
+               for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) {
+                       pn[i]++;