提交 1ad4f639 编写于 作者: E Eliad Peller 提交者: Johannes Berg

iwlwifi: mvm: move TX PN assignment for TKIP to the driver

If protocol offloading is configured, the fw might generate some
frames (e.g. arp response) on its own during d3/d0i3.

On d3/d0i3 exit the driver queries the updated PN (if relevant),
and updates its keys (for the d0i3 case, this is done by
iwl_mvm_d0i3_exit_work(), which is scheduled on d0i3 exit)

While in d0i3, iwlmvm defers tx frames until d0i3 exit, and
then continues their processing.

This is problematic with TKIP, since the frame's PN has already
been set at this stage (in contrast to CCMP, where the PN is
being set only later on), so both the frame's PN and the upcoming
PN update (from d0i3 exit work) might be wrong.

Fix it by moving the TX PN assignment (for TKIP) to the driver,
similarly to CCMP.
Signed-off-by: NEliad Peller <eliadx.peller@intel.com>
Signed-off-by: NEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: NJohannes Berg <johannes.berg@intel.com>
上级 f8079d43
...@@ -249,16 +249,19 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, ...@@ -249,16 +249,19 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
return; return;
case WLAN_CIPHER_SUITE_TKIP: case WLAN_CIPHER_SUITE_TKIP:
if (sta) { if (sta) {
u64 pn64;
tkip_sc = data->rsc_tsc->all_tsc_rsc.tkip.unicast_rsc; tkip_sc = data->rsc_tsc->all_tsc_rsc.tkip.unicast_rsc;
tkip_tx_sc = &data->rsc_tsc->all_tsc_rsc.tkip.tsc; tkip_tx_sc = &data->rsc_tsc->all_tsc_rsc.tkip.tsc;
rx_p1ks = data->tkip->rx_uni; rx_p1ks = data->tkip->rx_uni;
ieee80211_get_key_tx_seq(key, &seq); pn64 = atomic64_read(&key->tx_pn);
tkip_tx_sc->iv16 = cpu_to_le16(seq.tkip.iv16); tkip_tx_sc->iv16 = cpu_to_le16(TKIP_PN_TO_IV16(pn64));
tkip_tx_sc->iv32 = cpu_to_le32(seq.tkip.iv32); tkip_tx_sc->iv32 = cpu_to_le32(TKIP_PN_TO_IV32(pn64));
ieee80211_get_tkip_p1k_iv(key, seq.tkip.iv32, p1k); ieee80211_get_tkip_p1k_iv(key, TKIP_PN_TO_IV32(pn64),
p1k);
iwl_mvm_convert_p1k(p1k, data->tkip->tx.p1k); iwl_mvm_convert_p1k(p1k, data->tkip->tx.p1k);
memcpy(data->tkip->mic_keys.tx, memcpy(data->tkip->mic_keys.tx,
...@@ -1601,7 +1604,9 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw, ...@@ -1601,7 +1604,9 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
case WLAN_CIPHER_SUITE_TKIP: case WLAN_CIPHER_SUITE_TKIP:
iwl_mvm_tkip_sc_to_seq(&sc->tkip.tsc, &seq); iwl_mvm_tkip_sc_to_seq(&sc->tkip.tsc, &seq);
iwl_mvm_set_tkip_rx_seq(sc->tkip.unicast_rsc, key); iwl_mvm_set_tkip_rx_seq(sc->tkip.unicast_rsc, key);
ieee80211_set_key_tx_seq(key, &seq); atomic64_set(&key->tx_pn,
(u64)seq.tkip.iv16 |
((u64)seq.tkip.iv32 << 16));
break; break;
} }
......
...@@ -2585,7 +2585,7 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, ...@@ -2585,7 +2585,7 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
switch (key->cipher) { switch (key->cipher) {
case WLAN_CIPHER_SUITE_TKIP: case WLAN_CIPHER_SUITE_TKIP:
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
break; break;
case WLAN_CIPHER_SUITE_CCMP: case WLAN_CIPHER_SUITE_CCMP:
key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE; key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
......
...@@ -299,6 +299,8 @@ static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm, ...@@ -299,6 +299,8 @@ static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm,
case WLAN_CIPHER_SUITE_TKIP: case WLAN_CIPHER_SUITE_TKIP:
tx_cmd->sec_ctl = TX_CMD_SEC_TKIP; tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
pn = atomic64_inc_return(&keyconf->tx_pn);
ieee80211_tkip_add_iv(crypto_hdr, keyconf, pn);
ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key); ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key);
break; break;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册