Skip to content

Commit

Permalink
mac80211: don't compare TKIP TX MIC key in reinstall prevention
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
jmberg-intel committed Oct 25, 2017
1 parent 0bfe649 commit cfbb0d9
Showing 1 changed file with 34 additions and 2 deletions.
36 changes: 34 additions & 2 deletions net/mac80211/key.c
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,39 @@ void ieee80211_key_free_unused(struct ieee80211_key *key)
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)
Expand All @@ -635,8 +668,7 @@ int ieee80211_key_link(struct ieee80211_key *key,
* 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;
Expand Down

0 comments on commit cfbb0d9

Please sign in to comment.