mac80211: backport fixes for fix for CVE-2017-13080
Backport two fixes for the fix of CVE-2017-13080, preventing side channel attacks and making it work for TKIP. Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
This commit is contained in:
parent
34958c8269
commit
1dcd8e7cf1
2 changed files with 106 additions and 0 deletions
|
@ -0,0 +1,33 @@
|
|||
From 2bdd713b92a9cade239d3c7d15205a09f556624d Mon Sep 17 00:00:00 2001
|
||||
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
|
||||
Date: Tue, 17 Oct 2017 20:32:07 +0200
|
||||
Subject: [PATCH] mac80211: use constant time comparison with keys
|
||||
|
||||
Otherwise we risk leaking information via timing side channel.
|
||||
|
||||
Fixes: fdf7cb4185b6 ("mac80211: accept key reinstall without changing anything")
|
||||
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
net/mac80211/key.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/net/mac80211/key.c
|
||||
+++ b/net/mac80211/key.c
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/export.h>
|
||||
#include <net/mac80211.h>
|
||||
+#include <crypto/algapi.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include "ieee80211_i.h"
|
||||
#include "driver-ops.h"
|
||||
@@ -635,7 +636,7 @@ int ieee80211_key_link(struct ieee80211_
|
||||
* new version of the key to avoid nonce reuse or replay issues.
|
||||
*/
|
||||
if (old_key && key->conf.keylen == old_key->conf.keylen &&
|
||||
- !memcmp(key->conf.key, old_key->conf.key, key->conf.keylen)) {
|
||||
+ !crypto_memneq(key->conf.key, old_key->conf.key, key->conf.keylen)) {
|
||||
ieee80211_key_free_unused(key);
|
||||
ret = 0;
|
||||
goto out;
|
|
@ -0,0 +1,73 @@
|
|||
From cfbb0d90a7abb289edc91833d0905931f8805f12 Mon Sep 17 00:00:00 2001
|
||||
From: Johannes Berg <johannes.berg@intel.com>
|
||||
Date: Tue, 24 Oct 2017 21:12:13 +0200
|
||||
Subject: [PATCH] mac80211: don't compare TKIP TX MIC key in reinstall prevention
|
||||
|
||||
For the reinstall prevention, the code I had added compares the
|
||||
whole key. It turns out though that iwlwifi firmware doesn't
|
||||
provide the TKIP TX MIC key as it's not needed in client mode,
|
||||
and thus the comparison will always return false.
|
||||
|
||||
For client mode, thus always zero out the TX MIC key part before
|
||||
doing the comparison in order to avoid accepting the reinstall
|
||||
of the key with identical encryption and RX MIC key, but not the
|
||||
same TX MIC key (since the supplicant provides the real one.)
|
||||
|
||||
Fixes: fdf7cb4185b6 ("mac80211: accept key reinstall without changing anything")
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
net/mac80211/key.c | 36 ++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 34 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/net/mac80211/key.c
|
||||
+++ b/net/mac80211/key.c
|
||||
@@ -610,6 +610,39 @@ void ieee80211_key_free_unused(struct ie
|
||||
ieee80211_key_free_common(key);
|
||||
}
|
||||
|
||||
+static bool ieee80211_key_identical(struct ieee80211_sub_if_data *sdata,
|
||||
+ struct ieee80211_key *old,
|
||||
+ struct ieee80211_key *new)
|
||||
+{
|
||||
+ u8 tkip_old[WLAN_KEY_LEN_TKIP], tkip_new[WLAN_KEY_LEN_TKIP];
|
||||
+ u8 *tk_old, *tk_new;
|
||||
+
|
||||
+ if (!old || new->conf.keylen != old->conf.keylen)
|
||||
+ return false;
|
||||
+
|
||||
+ tk_old = old->conf.key;
|
||||
+ tk_new = new->conf.key;
|
||||
+
|
||||
+ /*
|
||||
+ * In station mode, don't compare the TX MIC key, as it's never used
|
||||
+ * and offloaded rekeying may not care to send it to the host. This
|
||||
+ * is the case in iwlwifi, for example.
|
||||
+ */
|
||||
+ if (sdata->vif.type == NL80211_IFTYPE_STATION &&
|
||||
+ new->conf.cipher == WLAN_CIPHER_SUITE_TKIP &&
|
||||
+ new->conf.keylen == WLAN_KEY_LEN_TKIP &&
|
||||
+ !(new->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
|
||||
+ memcpy(tkip_old, tk_old, WLAN_KEY_LEN_TKIP);
|
||||
+ memcpy(tkip_new, tk_new, WLAN_KEY_LEN_TKIP);
|
||||
+ memset(tkip_old + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, 0, 8);
|
||||
+ memset(tkip_new + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, 0, 8);
|
||||
+ tk_old = tkip_old;
|
||||
+ tk_new = tkip_new;
|
||||
+ }
|
||||
+
|
||||
+ return !crypto_memneq(tk_old, tk_new, new->conf.keylen);
|
||||
+}
|
||||
+
|
||||
int ieee80211_key_link(struct ieee80211_key *key,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
struct sta_info *sta)
|
||||
@@ -635,8 +668,7 @@ int ieee80211_key_link(struct ieee80211_
|
||||
* Silently accept key re-installation without really installing the
|
||||
* new version of the key to avoid nonce reuse or replay issues.
|
||||
*/
|
||||
- if (old_key && key->conf.keylen == old_key->conf.keylen &&
|
||||
- !crypto_memneq(key->conf.key, old_key->conf.key, key->conf.keylen)) {
|
||||
+ if (ieee80211_key_identical(sdata, old_key, key)) {
|
||||
ieee80211_key_free_unused(key);
|
||||
ret = 0;
|
||||
goto out;
|
Loading…
Reference in a new issue