Commit a6dfbd04 authored by Johannes Berg's avatar Johannes Berg Committed by Luca Coelho

iwlwifi: mvm: set replay counter on key install

When installing a (new) key, set the replay counter so that
after FW restart the firmware has the correct value of the
replay counters.

This doesn't have a large effect - for frames that reach
the driver, it will do a replay check, and when installing
a new key, the counter is normally zero to start with (not
for GTK though, if joining the BSS for the first time).

Since this only affects frames handled entirely by the FW,
and that's restricted to a few unicast management frames,
the only affect here is for those after a firmware restart.
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.20210802172232.1cedf2ca7bb6.I2e609c28eaa301436e6740f4f1beca838f69a96a@changeidSigned-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent 1a81bddf
...@@ -3190,6 +3190,20 @@ static struct iwl_mvm_sta *iwl_mvm_get_key_sta(struct iwl_mvm *mvm, ...@@ -3190,6 +3190,20 @@ static struct iwl_mvm_sta *iwl_mvm_get_key_sta(struct iwl_mvm *mvm,
return NULL; return NULL;
} }
static int iwl_mvm_pn_cmp(const u8 *pn1, const u8 *pn2, int len)
{
int i;
for (i = len - 1; i >= 0; i--) {
if (pn1[i] > pn2[i])
return 1;
if (pn1[i] < pn2[i])
return -1;
}
return 0;
}
static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm, static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
u32 sta_id, u32 sta_id,
struct ieee80211_key_conf *key, bool mcast, struct ieee80211_key_conf *key, bool mcast,
...@@ -3274,6 +3288,45 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm, ...@@ -3274,6 +3288,45 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
u.cmd.common.key_flags = key_flags; u.cmd.common.key_flags = key_flags;
u.cmd.common.sta_id = sta_id; u.cmd.common.sta_id = sta_id;
if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
i = 0;
else
i = -1;
for (; i < IEEE80211_NUM_TIDS; i++) {
struct ieee80211_key_seq seq = {};
u8 _rx_pn[IEEE80211_MAX_PN_LEN] = {}, *rx_pn = _rx_pn;
int rx_pn_len = 8;
ieee80211_get_key_rx_seq(key, i, &seq);
if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
rx_pn[0] = seq.tkip.iv16;
rx_pn[1] = seq.tkip.iv16 >> 8;
/* hole at 2/3 in FW format */
rx_pn[4] = seq.tkip.iv32;
rx_pn[5] = seq.tkip.iv32 >> 8;
rx_pn[6] = seq.tkip.iv32 >> 16;
rx_pn[7] = seq.tkip.iv32 >> 24;
} else if (key_flags & cpu_to_le16(STA_KEY_FLG_EXT)) {
rx_pn = seq.hw.seq;
rx_pn_len = seq.hw.seq_len;
} else {
rx_pn[0] = seq.ccmp.pn[0];
rx_pn[1] = seq.ccmp.pn[1];
/* hole at 2/3 in FW format */
rx_pn[4] = seq.ccmp.pn[2];
rx_pn[5] = seq.ccmp.pn[3];
rx_pn[6] = seq.ccmp.pn[4];
rx_pn[7] = seq.ccmp.pn[5];
}
if (iwl_mvm_pn_cmp(rx_pn, (u8 *)&u.cmd.common.rx_secur_seq_cnt,
rx_pn_len) > 0)
memcpy(&u.cmd.common.rx_secur_seq_cnt, rx_pn,
rx_pn_len);
}
if (new_api) { if (new_api) {
u.cmd.transmit_seq_cnt = cpu_to_le64(pn); u.cmd.transmit_seq_cnt = cpu_to_le64(pn);
size = sizeof(u.cmd); size = sizeof(u.cmd);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment