ath: Modify ath_key_delete() to not need full key entry

commit 144cd24dbc36650a51f7fe3bf1424a1432f1f480 upstream.

tkip_keymap can be used internally to avoid the reference to key->cipher
and with this, only the key index value itself is needed. This allows
ath_key_delete() call to be postponed to be handled after the upper
layer STA and key entry have already been removed. This is needed to
make ath9k key cache management safer.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20201214172118.18100-5-jouni@codeaurora.org
Cc: Pali Rohár <pali@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Jouni Malinen
2020-12-14 19:21:17 +02:00
committed by Sasha Levin
parent 2925a8385e
commit 609c0cfd07
5 changed files with 22 additions and 23 deletions

View File

@@ -581,38 +581,38 @@ EXPORT_SYMBOL(ath_key_config);
/*
* Delete Key.
*/
void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf *key)
void ath_key_delete(struct ath_common *common, u8 hw_key_idx)
{
/* Leave CCMP and TKIP (main key) configured to avoid disabling
* encryption for potentially pending frames already in a TXQ with the
* keyix pointing to this key entry. Instead, only clear the MAC address
* to prevent RX processing from using this key cache entry.
*/
if (test_bit(key->hw_key_idx, common->ccmp_keymap) ||
test_bit(key->hw_key_idx, common->tkip_keymap))
ath_hw_keysetmac(common, key->hw_key_idx, NULL);
if (test_bit(hw_key_idx, common->ccmp_keymap) ||
test_bit(hw_key_idx, common->tkip_keymap))
ath_hw_keysetmac(common, hw_key_idx, NULL);
else
ath_hw_keyreset(common, key->hw_key_idx);
if (key->hw_key_idx < IEEE80211_WEP_NKID)
ath_hw_keyreset(common, hw_key_idx);
if (hw_key_idx < IEEE80211_WEP_NKID)
return;
clear_bit(key->hw_key_idx, common->keymap);
clear_bit(key->hw_key_idx, common->ccmp_keymap);
if (key->cipher != WLAN_CIPHER_SUITE_TKIP)
clear_bit(hw_key_idx, common->keymap);
clear_bit(hw_key_idx, common->ccmp_keymap);
if (!test_bit(hw_key_idx, common->tkip_keymap))
return;
clear_bit(key->hw_key_idx + 64, common->keymap);
clear_bit(hw_key_idx + 64, common->keymap);
clear_bit(key->hw_key_idx, common->tkip_keymap);
clear_bit(key->hw_key_idx + 64, common->tkip_keymap);
clear_bit(hw_key_idx, common->tkip_keymap);
clear_bit(hw_key_idx + 64, common->tkip_keymap);
if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) {
ath_hw_keyreset(common, key->hw_key_idx + 32);
clear_bit(key->hw_key_idx + 32, common->keymap);
clear_bit(key->hw_key_idx + 64 + 32, common->keymap);
ath_hw_keyreset(common, hw_key_idx + 32);
clear_bit(hw_key_idx + 32, common->keymap);
clear_bit(hw_key_idx + 64 + 32, common->keymap);
clear_bit(key->hw_key_idx + 32, common->tkip_keymap);
clear_bit(key->hw_key_idx + 64 + 32, common->tkip_keymap);
clear_bit(hw_key_idx + 32, common->tkip_keymap);
clear_bit(hw_key_idx + 64 + 32, common->tkip_keymap);
}
}
EXPORT_SYMBOL(ath_key_delete);