ath: Modify ath_key_delete() to not need full key entry
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
This commit is contained in:
parent
d2d3e36498
commit
144cd24dbc
@ -197,7 +197,7 @@ struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
|
||||
bool ath_is_mybeacon(struct ath_common *common, struct ieee80211_hdr *hdr);
|
||||
|
||||
void ath_hw_setbssidmask(struct ath_common *common);
|
||||
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);
|
||||
int ath_key_config(struct ath_common *common,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
|
@ -522,7 +522,7 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
}
|
||||
break;
|
||||
case DISABLE_KEY:
|
||||
ath_key_delete(common, key);
|
||||
ath_key_delete(common, key->hw_key_idx);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
|
@ -1461,7 +1461,7 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw,
|
||||
}
|
||||
break;
|
||||
case DISABLE_KEY:
|
||||
ath_key_delete(common, key);
|
||||
ath_key_delete(common, key->hw_key_idx);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
|
@ -1543,12 +1543,11 @@ static void ath9k_del_ps_key(struct ath_softc *sc,
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ath_node *an = (struct ath_node *) sta->drv_priv;
|
||||
struct ieee80211_key_conf ps_key = { .hw_key_idx = an->ps_key };
|
||||
|
||||
if (!an->ps_key)
|
||||
return;
|
||||
|
||||
ath_key_delete(common, &ps_key);
|
||||
ath_key_delete(common, an->ps_key);
|
||||
an->ps_key = 0;
|
||||
an->key_idx[0] = 0;
|
||||
}
|
||||
@ -1748,7 +1747,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
|
||||
}
|
||||
break;
|
||||
case DISABLE_KEY:
|
||||
ath_key_delete(common, key);
|
||||
ath_key_delete(common, key->hw_key_idx);
|
||||
if (an) {
|
||||
for (i = 0; i < ARRAY_SIZE(an->key_idx); i++) {
|
||||
if (an->key_idx[i] != key->hw_key_idx)
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user