Commit 85aeb58c authored by David Spinadel's avatar David Spinadel Committed by Luca Coelho

iwlwifi: mvm: Enable security on new TX API

Install GTKs on AP side for new TX API.
Don't add IV space, it's added by the HW.

While at that fix GCMP abnd GCMP-256 GTK installation
which work similarly to the new TX API.
Signed-off-by: default avatarDavid Spinadel <david.spinadel@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent f45f979d
...@@ -2883,6 +2883,7 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, ...@@ -2883,6 +2883,7 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
case WLAN_CIPHER_SUITE_CCMP: case WLAN_CIPHER_SUITE_CCMP:
case WLAN_CIPHER_SUITE_GCMP: case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256: case WLAN_CIPHER_SUITE_GCMP_256:
if (!iwl_mvm_has_new_tx_api(mvm))
key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE; key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
break; break;
case WLAN_CIPHER_SUITE_AES_CMAC: case WLAN_CIPHER_SUITE_AES_CMAC:
...@@ -2929,9 +2930,14 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, ...@@ -2929,9 +2930,14 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
ret = -EOPNOTSUPP; ret = -EOPNOTSUPP;
else else
ret = 0; ret = 0;
if (key->cipher != WLAN_CIPHER_SUITE_GCMP &&
key->cipher != WLAN_CIPHER_SUITE_GCMP_256 &&
!iwl_mvm_has_new_tx_api(mvm)) {
key->hw_key_idx = STA_KEY_IDX_INVALID; key->hw_key_idx = STA_KEY_IDX_INVALID;
break; break;
} }
}
/* During FW restart, in order to restore the state as it was, /* During FW restart, in order to restore the state as it was,
* don't try to reprogram keys we previously failed for. * don't try to reprogram keys we previously failed for.
......
...@@ -2980,7 +2980,7 @@ static struct iwl_mvm_sta *iwl_mvm_get_key_sta(struct iwl_mvm *mvm, ...@@ -2980,7 +2980,7 @@ static struct iwl_mvm_sta *iwl_mvm_get_key_sta(struct iwl_mvm *mvm,
} }
static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm, static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
struct iwl_mvm_sta *mvm_sta, u32 sta_id,
struct ieee80211_key_conf *key, bool mcast, struct ieee80211_key_conf *key, bool mcast,
u32 tkip_iv32, u16 *tkip_p1k, u32 cmd_flags, u32 tkip_iv32, u16 *tkip_p1k, u32 cmd_flags,
u8 key_offset) u8 key_offset)
...@@ -2998,6 +2998,9 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm, ...@@ -2998,6 +2998,9 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
bool new_api = fw_has_api(&mvm->fw->ucode_capa, bool new_api = fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_TKIP_MIC_KEYS); IWL_UCODE_TLV_API_TKIP_MIC_KEYS);
if (sta_id == IWL_MVM_INVALID_STA)
return -EINVAL;
keyidx = (key->keyidx << STA_KEY_FLG_KEYID_POS) & keyidx = (key->keyidx << STA_KEY_FLG_KEYID_POS) &
STA_KEY_FLG_KEYID_MSK; STA_KEY_FLG_KEYID_MSK;
key_flags = cpu_to_le16(keyidx); key_flags = cpu_to_le16(keyidx);
...@@ -3056,7 +3059,7 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm, ...@@ -3056,7 +3059,7 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
u.cmd.common.key_offset = key_offset; u.cmd.common.key_offset = key_offset;
u.cmd.common.key_flags = key_flags; u.cmd.common.key_flags = key_flags;
u.cmd.common.sta_id = mvm_sta->sta_id; u.cmd.common.sta_id = sta_id;
if (new_api) { if (new_api) {
u.cmd.transmit_seq_cnt = cpu_to_le64(pn); u.cmd.transmit_seq_cnt = cpu_to_le64(pn);
...@@ -3189,19 +3192,37 @@ static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm, ...@@ -3189,19 +3192,37 @@ static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
u8 key_offset, u8 key_offset,
bool mcast) bool mcast)
{ {
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
int ret; int ret;
const u8 *addr; const u8 *addr;
struct ieee80211_key_seq seq; struct ieee80211_key_seq seq;
u16 p1k[5]; u16 p1k[5];
u32 sta_id;
if (sta) {
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
sta_id = mvm_sta->sta_id;
} else if (vif->type == NL80211_IFTYPE_AP &&
!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
sta_id = mvmvif->mcast_sta.sta_id;
} else {
IWL_ERR(mvm, "Failed to find station id\n");
return -EINVAL;
}
switch (keyconf->cipher) { switch (keyconf->cipher) {
case WLAN_CIPHER_SUITE_TKIP: case WLAN_CIPHER_SUITE_TKIP:
if (vif->type == NL80211_IFTYPE_AP) {
ret = -EINVAL;
break;
}
addr = iwl_mvm_get_mac_addr(mvm, vif, sta); addr = iwl_mvm_get_mac_addr(mvm, vif, sta);
/* get phase 1 key from mac80211 */ /* get phase 1 key from mac80211 */
ieee80211_get_key_rx_seq(keyconf, 0, &seq); ieee80211_get_key_rx_seq(keyconf, 0, &seq);
ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k); ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k);
ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast, ret = iwl_mvm_send_sta_key(mvm, sta_id, keyconf, mcast,
seq.tkip.iv32, p1k, 0, key_offset); seq.tkip.iv32, p1k, 0, key_offset);
break; break;
case WLAN_CIPHER_SUITE_CCMP: case WLAN_CIPHER_SUITE_CCMP:
...@@ -3209,11 +3230,11 @@ static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm, ...@@ -3209,11 +3230,11 @@ static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
case WLAN_CIPHER_SUITE_WEP104: case WLAN_CIPHER_SUITE_WEP104:
case WLAN_CIPHER_SUITE_GCMP: case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256: case WLAN_CIPHER_SUITE_GCMP_256:
ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast, ret = iwl_mvm_send_sta_key(mvm, sta_id, keyconf, mcast,
0, NULL, 0, key_offset); 0, NULL, 0, key_offset);
break; break;
default: default:
ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast, ret = iwl_mvm_send_sta_key(mvm, sta_id, keyconf, mcast,
0, NULL, 0, key_offset); 0, NULL, 0, key_offset);
} }
...@@ -3234,6 +3255,9 @@ static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id, ...@@ -3234,6 +3255,9 @@ static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id,
int ret, size; int ret, size;
u32 status; u32 status;
if (sta_id == IWL_MVM_INVALID_STA)
return -EINVAL;
key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) & key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
STA_KEY_FLG_KEYID_MSK); STA_KEY_FLG_KEYID_MSK);
key_flags |= cpu_to_le16(STA_KEY_FLG_NO_ENC | STA_KEY_FLG_WEP_KEY_MAP); key_flags |= cpu_to_le16(STA_KEY_FLG_NO_ENC | STA_KEY_FLG_WEP_KEY_MAP);
...@@ -3277,12 +3301,14 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm, ...@@ -3277,12 +3301,14 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
{ {
bool mcast = !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE); bool mcast = !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE);
struct iwl_mvm_sta *mvm_sta; struct iwl_mvm_sta *mvm_sta;
u8 sta_id; u8 sta_id = IWL_MVM_INVALID_STA;
int ret; int ret;
static const u8 __maybe_unused zero_addr[ETH_ALEN] = {0}; static const u8 __maybe_unused zero_addr[ETH_ALEN] = {0};
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
if (vif->type != NL80211_IFTYPE_AP ||
keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
/* Get the station id from the mvm local station table */ /* Get the station id from the mvm local station table */
mvm_sta = iwl_mvm_get_key_sta(mvm, vif, sta); mvm_sta = iwl_mvm_get_key_sta(mvm, vif, sta);
if (!mvm_sta) { if (!mvm_sta) {
...@@ -3294,16 +3320,19 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm, ...@@ -3294,16 +3320,19 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC || if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 || keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256) { keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256) {
ret = iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id, false); ret = iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id,
false);
goto end; goto end;
} }
/* /*
* It is possible that the 'sta' parameter is NULL, and thus * It is possible that the 'sta' parameter is NULL, and thus
* there is a need to retrieve the sta from the local station table. * there is a need to retrieve the sta from the local station
* table.
*/ */
if (!sta) { if (!sta) {
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id], sta = rcu_dereference_protected(
mvm->fw_id_to_mac_id[sta_id],
lockdep_is_held(&mvm->mutex)); lockdep_is_held(&mvm->mutex));
if (IS_ERR_OR_NULL(sta)) { if (IS_ERR_OR_NULL(sta)) {
IWL_ERR(mvm, "Invalid station id\n"); IWL_ERR(mvm, "Invalid station id\n");
...@@ -3313,6 +3342,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm, ...@@ -3313,6 +3342,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
if (WARN_ON_ONCE(iwl_mvm_sta_from_mac80211(sta)->vif != vif)) if (WARN_ON_ONCE(iwl_mvm_sta_from_mac80211(sta)->vif != vif))
return -EINVAL; return -EINVAL;
}
/* If the key_offset is not pre-assigned, we need to find a /* If the key_offset is not pre-assigned, we need to find a
* new offset to use. In normal cases, the offset is not * new offset to use. In normal cases, the offset is not
...@@ -3342,8 +3372,9 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm, ...@@ -3342,8 +3372,9 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
* to the same key slot (offset). * to the same key slot (offset).
* If this fails, remove the original as well. * If this fails, remove the original as well.
*/ */
if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 || if ((keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) { keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) &&
sta) {
ret = __iwl_mvm_set_sta_key(mvm, vif, sta, keyconf, ret = __iwl_mvm_set_sta_key(mvm, vif, sta, keyconf,
key_offset, !mcast); key_offset, !mcast);
if (ret) { if (ret) {
...@@ -3377,6 +3408,9 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, ...@@ -3377,6 +3408,9 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
mvm_sta = iwl_mvm_get_key_sta(mvm, vif, sta); mvm_sta = iwl_mvm_get_key_sta(mvm, vif, sta);
if (mvm_sta) if (mvm_sta)
sta_id = mvm_sta->sta_id; sta_id = mvm_sta->sta_id;
else if (!sta && vif->type == NL80211_IFTYPE_AP && mcast)
sta_id = iwl_mvm_vif_from_mac80211(vif)->mcast_sta.sta_id;
IWL_DEBUG_WEP(mvm, "mvm remove dynamic key: idx=%d sta=%d\n", IWL_DEBUG_WEP(mvm, "mvm remove dynamic key: idx=%d sta=%d\n",
keyconf->keyidx, sta_id); keyconf->keyidx, sta_id);
...@@ -3399,7 +3433,7 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, ...@@ -3399,7 +3433,7 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
} }
mvm->fw_key_deleted[keyconf->hw_key_idx] = 0; mvm->fw_key_deleted[keyconf->hw_key_idx] = 0;
if (!mvm_sta) { if (sta && !mvm_sta) {
IWL_DEBUG_WEP(mvm, "station non-existent, early return.\n"); IWL_DEBUG_WEP(mvm, "station non-existent, early return.\n");
return 0; return 0;
} }
...@@ -3430,7 +3464,7 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm, ...@@ -3430,7 +3464,7 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,
mvm_sta = iwl_mvm_get_key_sta(mvm, vif, sta); mvm_sta = iwl_mvm_get_key_sta(mvm, vif, sta);
if (WARN_ON_ONCE(!mvm_sta)) if (WARN_ON_ONCE(!mvm_sta))
goto unlock; goto unlock;
iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast, iwl_mvm_send_sta_key(mvm, mvm_sta->sta_id, keyconf, mcast,
iv32, phase1key, CMD_ASYNC, keyconf->hw_key_idx); iv32, phase1key, CMD_ASYNC, keyconf->hw_key_idx);
unlock: unlock:
......
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