Skip to content
Snippets Groups Projects
Commit e257d969 authored by Johannes Berg's avatar Johannes Berg Committed by Luca Coelho
Browse files

iwlwifi: mvm: don't use FW key ID in beacon protection


To check beacon protection had a mismatch of the key ID we
currently use the key ID from the firmware, but firmware
side we want to clean up the API to stop reporting this.

Instead, check the IWL_RX_MPDU_STATUS_KEY_VALID bit that
indicates that the firmware used the correct key, and if
that's set but we get invalid MIC/replay use the key ID
from the frame to look up the key and notify mac80211 of
MIC error or replay. Since both keys must have the same
cipher and thus MIC length, we can use either of them to
look up the MIC length.

Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20210826224715.30e665d39b07.I78bf7d304ef5a80cecf5fa1c1fca0b51b956cceb@changeid


Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent 090f1be3
No related branches found
No related tags found
No related merge requests found
...@@ -279,7 +279,6 @@ static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta, ...@@ -279,7 +279,6 @@ static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta,
{ {
struct iwl_mvm_sta *mvmsta; struct iwl_mvm_sta *mvmsta;
struct iwl_mvm_vif *mvmvif; struct iwl_mvm_vif *mvmvif;
u8 fwkeyid = u32_get_bits(status, IWL_RX_MPDU_STATUS_KEY);
u8 keyid; u8 keyid;
struct ieee80211_key_conf *key; struct ieee80211_key_conf *key;
u32 len = le16_to_cpu(desc->mpdu_len); u32 len = le16_to_cpu(desc->mpdu_len);
...@@ -299,6 +298,10 @@ static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta, ...@@ -299,6 +298,10 @@ static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta,
if (!ieee80211_is_beacon(hdr->frame_control)) if (!ieee80211_is_beacon(hdr->frame_control))
return 0; return 0;
/* key mismatch - will also report !MIC_OK but we shouldn't count it */
if (!(status & IWL_RX_MPDU_STATUS_KEY_VALID))
return -1;
/* good cases */ /* good cases */
if (likely(status & IWL_RX_MPDU_STATUS_MIC_OK && if (likely(status & IWL_RX_MPDU_STATUS_MIC_OK &&
!(status & IWL_RX_MPDU_STATUS_REPLAY_ERROR))) !(status & IWL_RX_MPDU_STATUS_REPLAY_ERROR)))
...@@ -309,26 +312,36 @@ static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta, ...@@ -309,26 +312,36 @@ static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta,
mvmsta = iwl_mvm_sta_from_mac80211(sta); mvmsta = iwl_mvm_sta_from_mac80211(sta);
/* what? */
if (fwkeyid != 6 && fwkeyid != 7)
return -1;
mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif); mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
key = rcu_dereference(mvmvif->bcn_prot.keys[fwkeyid - 6]); /*
if (!key) * both keys will have the same cipher and MIC length, use
return -1; * whichever one is available
*/
key = rcu_dereference(mvmvif->bcn_prot.keys[0]);
if (!key) {
key = rcu_dereference(mvmvif->bcn_prot.keys[1]);
if (!key)
return -1;
}
if (len < key->icv_len + IEEE80211_GMAC_PN_LEN + 2) if (len < key->icv_len + IEEE80211_GMAC_PN_LEN + 2)
return -1; return -1;
/* /* get the real key ID */
* See if the key ID matches - if not this may be due to a
* switch and the firmware may erroneously report !MIC_OK.
*/
keyid = frame[len - key->icv_len - IEEE80211_GMAC_PN_LEN - 2]; keyid = frame[len - key->icv_len - IEEE80211_GMAC_PN_LEN - 2];
if (keyid != fwkeyid) /* and if that's the other key, look it up */
return -1; if (keyid != key->keyidx) {
/*
* shouldn't happen since firmware checked, but be safe
* in case the MIC length is wrong too, for example
*/
if (keyid != 6 && keyid != 7)
return -1;
key = rcu_dereference(mvmvif->bcn_prot.keys[keyid - 6]);
if (!key)
return -1;
}
/* Report status to mac80211 */ /* Report status to mac80211 */
if (!(status & IWL_RX_MPDU_STATUS_MIC_OK)) if (!(status & IWL_RX_MPDU_STATUS_MIC_OK))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment