Skip to content

Commit ddd95bc

Browse files
jmberg-intelgregkh
authored andcommitted
mac80211: don't compare TKIP TX MIC key in reinstall prevention
commit cfbb0d9 upstream. 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: fdf7cb4 ("mac80211: accept key reinstall without changing anything") Signed-off-by: Johannes Berg <johannes.berg@intel.com> Cc: Ben Hutchings <ben.hutchings@codethink.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 38762a5 commit ddd95bc

File tree

1 file changed

+34
-2
lines changed

1 file changed

+34
-2
lines changed

net/mac80211/key.c

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,39 @@ void ieee80211_key_free_unused(struct ieee80211_key *key)
609609
ieee80211_key_free_common(key);
610610
}
611611

612+
static bool ieee80211_key_identical(struct ieee80211_sub_if_data *sdata,
613+
struct ieee80211_key *old,
614+
struct ieee80211_key *new)
615+
{
616+
u8 tkip_old[WLAN_KEY_LEN_TKIP], tkip_new[WLAN_KEY_LEN_TKIP];
617+
u8 *tk_old, *tk_new;
618+
619+
if (!old || new->conf.keylen != old->conf.keylen)
620+
return false;
621+
622+
tk_old = old->conf.key;
623+
tk_new = new->conf.key;
624+
625+
/*
626+
* In station mode, don't compare the TX MIC key, as it's never used
627+
* and offloaded rekeying may not care to send it to the host. This
628+
* is the case in iwlwifi, for example.
629+
*/
630+
if (sdata->vif.type == NL80211_IFTYPE_STATION &&
631+
new->conf.cipher == WLAN_CIPHER_SUITE_TKIP &&
632+
new->conf.keylen == WLAN_KEY_LEN_TKIP &&
633+
!(new->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
634+
memcpy(tkip_old, tk_old, WLAN_KEY_LEN_TKIP);
635+
memcpy(tkip_new, tk_new, WLAN_KEY_LEN_TKIP);
636+
memset(tkip_old + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, 0, 8);
637+
memset(tkip_new + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, 0, 8);
638+
tk_old = tkip_old;
639+
tk_new = tkip_new;
640+
}
641+
642+
return !crypto_memneq(tk_old, tk_new, new->conf.keylen);
643+
}
644+
612645
int ieee80211_key_link(struct ieee80211_key *key,
613646
struct ieee80211_sub_if_data *sdata,
614647
struct sta_info *sta)
@@ -634,8 +667,7 @@ int ieee80211_key_link(struct ieee80211_key *key,
634667
* Silently accept key re-installation without really installing the
635668
* new version of the key to avoid nonce reuse or replay issues.
636669
*/
637-
if (old_key && key->conf.keylen == old_key->conf.keylen &&
638-
!crypto_memneq(key->conf.key, old_key->conf.key, key->conf.keylen)) {
670+
if (ieee80211_key_identical(sdata, old_key, key)) {
639671
ieee80211_key_free_unused(key);
640672
ret = 0;
641673
goto out;

0 commit comments

Comments
 (0)