aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2017-10-24 15:12:13 -0400
committerJohannes Berg <johannes.berg@intel.com>2017-10-25 05:04:45 -0400
commitcfbb0d90a7abb289edc91833d0905931f8805f12 (patch)
tree5bdf986177e4800adf4dd1766fac1f2f673c57d6
parent0bfe649fbb1337400065fa47679b381b2ac845f0 (diff)
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>
-rw-r--r--net/mac80211/key.c36
1 files changed, 34 insertions, 2 deletions
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 035d16fe926e..938049395f90 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -610,6 +610,39 @@ void ieee80211_key_free_unused(struct ieee80211_key *key)
610 ieee80211_key_free_common(key); 610 ieee80211_key_free_common(key);
611} 611}
612 612
613static bool ieee80211_key_identical(struct ieee80211_sub_if_data *sdata,
614 struct ieee80211_key *old,
615 struct ieee80211_key *new)
616{
617 u8 tkip_old[WLAN_KEY_LEN_TKIP], tkip_new[WLAN_KEY_LEN_TKIP];
618 u8 *tk_old, *tk_new;
619
620 if (!old || new->conf.keylen != old->conf.keylen)
621 return false;
622
623 tk_old = old->conf.key;
624 tk_new = new->conf.key;
625
626 /*
627 * In station mode, don't compare the TX MIC key, as it's never used
628 * and offloaded rekeying may not care to send it to the host. This
629 * is the case in iwlwifi, for example.
630 */
631 if (sdata->vif.type == NL80211_IFTYPE_STATION &&
632 new->conf.cipher == WLAN_CIPHER_SUITE_TKIP &&
633 new->conf.keylen == WLAN_KEY_LEN_TKIP &&
634 !(new->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
635 memcpy(tkip_old, tk_old, WLAN_KEY_LEN_TKIP);
636 memcpy(tkip_new, tk_new, WLAN_KEY_LEN_TKIP);
637 memset(tkip_old + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, 0, 8);
638 memset(tkip_new + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, 0, 8);
639 tk_old = tkip_old;
640 tk_new = tkip_new;
641 }
642
643 return !crypto_memneq(tk_old, tk_new, new->conf.keylen);
644}
645
613int ieee80211_key_link(struct ieee80211_key *key, 646int ieee80211_key_link(struct ieee80211_key *key,
614 struct ieee80211_sub_if_data *sdata, 647 struct ieee80211_sub_if_data *sdata,
615 struct sta_info *sta) 648 struct sta_info *sta)
@@ -635,8 +668,7 @@ int ieee80211_key_link(struct ieee80211_key *key,
635 * Silently accept key re-installation without really installing the 668 * Silently accept key re-installation without really installing the
636 * new version of the key to avoid nonce reuse or replay issues. 669 * new version of the key to avoid nonce reuse or replay issues.
637 */ 670 */
638 if (old_key && key->conf.keylen == old_key->conf.keylen && 671 if (ieee80211_key_identical(sdata, old_key, key)) {
639 !crypto_memneq(key->conf.key, old_key->conf.key, key->conf.keylen)) {
640 ieee80211_key_free_unused(key); 672 ieee80211_key_free_unused(key);
641 ret = 0; 673 ret = 0;
642 goto out; 674 goto out;