Takashi Iwai 6f2bb2
From 94034c40ab4a3fcf581fbc7f8fdf4e29943c4a24 Mon Sep 17 00:00:00 2001
Takashi Iwai 6f2bb2
From: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
Takashi Iwai 6f2bb2
Date: Tue, 11 May 2021 20:02:43 +0200
Takashi Iwai 6f2bb2
Subject: [PATCH] mac80211: prevent mixed key and fragment cache attacks
Takashi Iwai 6f2bb2
Git-commit: 94034c40ab4a3fcf581fbc7f8fdf4e29943c4a24
Takashi Iwai 6f2bb2
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
Takashi Iwai 6f2bb2
Patch-mainline: Queued in subsystem maintainer repo
Takashi Iwai 6f2bb2
References: CVE-2020-24587 CVE-2020-24586 bsc#1185863 bsc#1185862 bsc#1185859
Takashi Iwai 6f2bb2
Takashi Iwai 6f2bb2
Simultaneously prevent mixed key attacks (CVE-2020-24587) and fragment
Takashi Iwai 6f2bb2
cache attacks (CVE-2020-24586). This is accomplished by assigning a
Takashi Iwai 6f2bb2
unique color to every key (per interface) and using this to track which
Takashi Iwai 6f2bb2
key was used to decrypt a fragment. When reassembling frames, it is
Takashi Iwai 6f2bb2
now checked whether all fragments were decrypted using the same key.
Takashi Iwai 6f2bb2
Takashi Iwai 6f2bb2
To assure that fragment cache attacks are also prevented, the ID that is
Takashi Iwai 6f2bb2
assigned to keys is unique even over (re)associations and (re)connects.
Takashi Iwai 6f2bb2
This means fragments separated by a (re)association or (re)connect will
Takashi Iwai 6f2bb2
not be reassembled. Because mac80211 now also prevents the reassembly of
Takashi Iwai 6f2bb2
mixed encrypted and plaintext fragments, all cache attacks are prevented.
Takashi Iwai 6f2bb2
Takashi Iwai 6f2bb2
Cc: stable@vger.kernel.org
Takashi Iwai 6f2bb2
Signed-off-by: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
Takashi Iwai 6f2bb2
Link: https://lore.kernel.org/r/20210511200110.3f8290e59823.I622a67769ed39257327a362cfc09c812320eb979@changeid
Takashi Iwai 6f2bb2
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Takashi Iwai 6f2bb2
Acked-by: Takashi Iwai <tiwai@suse.de>
Takashi Iwai 6f2bb2
Takashi Iwai 6f2bb2
---
Takashi Iwai 6f2bb2
 net/mac80211/ieee80211_i.h |    1 +
Takashi Iwai 6f2bb2
 net/mac80211/key.c         |    7 +++++++
Takashi Iwai 6f2bb2
 net/mac80211/key.h         |    2 ++
Takashi Iwai 6f2bb2
 net/mac80211/rx.c          |    6 ++++++
Takashi Iwai 6f2bb2
 4 files changed, 16 insertions(+)
Takashi Iwai 6f2bb2
Takashi Iwai 6f2bb2
--- a/net/mac80211/ieee80211_i.h
Takashi Iwai 6f2bb2
+++ b/net/mac80211/ieee80211_i.h
Takashi Iwai 6f2bb2
@@ -99,6 +99,7 @@ struct ieee80211_fragment_entry {
Takashi Iwai 6f2bb2
 	u8 rx_queue;
Takashi Iwai 6f2bb2
 	bool check_sequential_pn; /* needed for CCMP/GCMP */
Takashi Iwai 6f2bb2
 	u8 last_pn[6]; /* PN of the last fragment if CCMP was used */
Takashi Iwai 6f2bb2
+	unsigned int key_color;
Takashi Iwai 6f2bb2
 };
Takashi Iwai 6f2bb2
 
Takashi Iwai 6f2bb2
 
Takashi Iwai 6f2bb2
--- a/net/mac80211/key.c
Takashi Iwai 6f2bb2
+++ b/net/mac80211/key.c
Takashi Iwai 6f2bb2
@@ -647,6 +647,7 @@ int ieee80211_key_link(struct ieee80211_
Takashi Iwai 6f2bb2
 		       struct ieee80211_sub_if_data *sdata,
Takashi Iwai 6f2bb2
 		       struct sta_info *sta)
Takashi Iwai 6f2bb2
 {
Takashi Iwai 6f2bb2
+	static atomic_t key_color = ATOMIC_INIT(0);
Takashi Iwai 6f2bb2
 	struct ieee80211_local *local = sdata->local;
Takashi Iwai 6f2bb2
 	struct ieee80211_key *old_key;
Takashi Iwai 6f2bb2
 	int idx = key->conf.keyidx;
Takashi Iwai 6f2bb2
@@ -682,6 +683,12 @@ int ieee80211_key_link(struct ieee80211_
Takashi Iwai 6f2bb2
 	key->sdata = sdata;
Takashi Iwai 6f2bb2
 	key->sta = sta;
Takashi Iwai 6f2bb2
 
Takashi Iwai 6f2bb2
+	/*
Takashi Iwai 6f2bb2
+	 * Assign a unique ID to every key so we can easily prevent mixed
Takashi Iwai 6f2bb2
+	 * key and fragment cache attacks.
Takashi Iwai 6f2bb2
+	 */
Takashi Iwai 6f2bb2
+	key->color = atomic_inc_return(&key_color);
Takashi Iwai 6f2bb2
+
Takashi Iwai 6f2bb2
 	increment_tailroom_need_count(sdata);
Takashi Iwai 6f2bb2
 
Takashi Iwai 6f2bb2
 	ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
Takashi Iwai 6f2bb2
--- a/net/mac80211/key.h
Takashi Iwai 6f2bb2
+++ b/net/mac80211/key.h
Takashi Iwai 6f2bb2
@@ -127,6 +127,8 @@ struct ieee80211_key {
Takashi Iwai 6f2bb2
 	} debugfs;
Takashi Iwai 6f2bb2
 #endif
Takashi Iwai 6f2bb2
 
Takashi Iwai 6f2bb2
+	unsigned int color;
Takashi Iwai 6f2bb2
+
Takashi Iwai 6f2bb2
 	/*
Takashi Iwai 6f2bb2
 	 * key config, must be last because it contains key
Takashi Iwai 6f2bb2
 	 * material as variable length member
Takashi Iwai 6f2bb2
--- a/net/mac80211/rx.c
Takashi Iwai 6f2bb2
+++ b/net/mac80211/rx.c
Takashi Iwai 6f2bb2
@@ -2033,6 +2033,7 @@ ieee80211_rx_h_defragment(struct ieee802
Takashi Iwai 6f2bb2
 			 * next fragment has a sequential PN value.
Takashi Iwai 6f2bb2
 			 */
Takashi Iwai 6f2bb2
 			entry->check_sequential_pn = true;
Takashi Iwai 6f2bb2
+			entry->key_color = rx->key->color;
Takashi Iwai 6f2bb2
 			memcpy(entry->last_pn,
Takashi Iwai 6f2bb2
 			       rx->key->u.ccmp.rx_pn[queue],
Takashi Iwai 6f2bb2
 			       IEEE80211_CCMP_PN_LEN);
Takashi Iwai 6f2bb2
@@ -2070,6 +2071,11 @@ ieee80211_rx_h_defragment(struct ieee802
Takashi Iwai 6f2bb2
 
Takashi Iwai 6f2bb2
 		if (!requires_sequential_pn(rx, fc))
Takashi Iwai 6f2bb2
 			return RX_DROP_UNUSABLE;
Takashi Iwai 6f2bb2
+
Takashi Iwai 6f2bb2
+		/* Prevent mixed key and fragment cache attacks */
Takashi Iwai 6f2bb2
+		if (entry->key_color != rx->key->color)
Takashi Iwai 6f2bb2
+			return RX_DROP_UNUSABLE;
Takashi Iwai 6f2bb2
+
Takashi Iwai 6f2bb2
 		memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN);
Takashi Iwai 6f2bb2
 		for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) {
Takashi Iwai 6f2bb2
 			pn[i]++;