Skip to content

Commit 85aeb58

Browse files
DavidSpinadellucacoelho
authored andcommitted
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: David Spinadel <[email protected]> Signed-off-by: Luca Coelho <[email protected]>
1 parent f45f979 commit 85aeb58

File tree

2 files changed

+80
-40
lines changed

2 files changed

+80
-40
lines changed

drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2883,7 +2883,8 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
28832883
case WLAN_CIPHER_SUITE_CCMP:
28842884
case WLAN_CIPHER_SUITE_GCMP:
28852885
case WLAN_CIPHER_SUITE_GCMP_256:
2886-
key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
2886+
if (!iwl_mvm_has_new_tx_api(mvm))
2887+
key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
28872888
break;
28882889
case WLAN_CIPHER_SUITE_AES_CMAC:
28892890
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
@@ -2929,8 +2930,13 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
29292930
ret = -EOPNOTSUPP;
29302931
else
29312932
ret = 0;
2932-
key->hw_key_idx = STA_KEY_IDX_INVALID;
2933-
break;
2933+
2934+
if (key->cipher != WLAN_CIPHER_SUITE_GCMP &&
2935+
key->cipher != WLAN_CIPHER_SUITE_GCMP_256 &&
2936+
!iwl_mvm_has_new_tx_api(mvm)) {
2937+
key->hw_key_idx = STA_KEY_IDX_INVALID;
2938+
break;
2939+
}
29342940
}
29352941

29362942
/* During FW restart, in order to restore the state as it was,

drivers/net/wireless/intel/iwlwifi/mvm/sta.c

Lines changed: 71 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2980,7 +2980,7 @@ static struct iwl_mvm_sta *iwl_mvm_get_key_sta(struct iwl_mvm *mvm,
29802980
}
29812981

29822982
static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
2983-
struct iwl_mvm_sta *mvm_sta,
2983+
u32 sta_id,
29842984
struct ieee80211_key_conf *key, bool mcast,
29852985
u32 tkip_iv32, u16 *tkip_p1k, u32 cmd_flags,
29862986
u8 key_offset)
@@ -2998,6 +2998,9 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
29982998
bool new_api = fw_has_api(&mvm->fw->ucode_capa,
29992999
IWL_UCODE_TLV_API_TKIP_MIC_KEYS);
30003000

3001+
if (sta_id == IWL_MVM_INVALID_STA)
3002+
return -EINVAL;
3003+
30013004
keyidx = (key->keyidx << STA_KEY_FLG_KEYID_POS) &
30023005
STA_KEY_FLG_KEYID_MSK;
30033006
key_flags = cpu_to_le16(keyidx);
@@ -3056,7 +3059,7 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
30563059

30573060
u.cmd.common.key_offset = key_offset;
30583061
u.cmd.common.key_flags = key_flags;
3059-
u.cmd.common.sta_id = mvm_sta->sta_id;
3062+
u.cmd.common.sta_id = sta_id;
30603063

30613064
if (new_api) {
30623065
u.cmd.transmit_seq_cnt = cpu_to_le64(pn);
@@ -3189,31 +3192,49 @@ static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
31893192
u8 key_offset,
31903193
bool mcast)
31913194
{
3192-
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
31933195
int ret;
31943196
const u8 *addr;
31953197
struct ieee80211_key_seq seq;
31963198
u16 p1k[5];
3199+
u32 sta_id;
3200+
3201+
if (sta) {
3202+
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
3203+
3204+
sta_id = mvm_sta->sta_id;
3205+
} else if (vif->type == NL80211_IFTYPE_AP &&
3206+
!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
3207+
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
3208+
3209+
sta_id = mvmvif->mcast_sta.sta_id;
3210+
} else {
3211+
IWL_ERR(mvm, "Failed to find station id\n");
3212+
return -EINVAL;
3213+
}
31973214

31983215
switch (keyconf->cipher) {
31993216
case WLAN_CIPHER_SUITE_TKIP:
3217+
if (vif->type == NL80211_IFTYPE_AP) {
3218+
ret = -EINVAL;
3219+
break;
3220+
}
32003221
addr = iwl_mvm_get_mac_addr(mvm, vif, sta);
32013222
/* get phase 1 key from mac80211 */
32023223
ieee80211_get_key_rx_seq(keyconf, 0, &seq);
32033224
ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k);
3204-
ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
3225+
ret = iwl_mvm_send_sta_key(mvm, sta_id, keyconf, mcast,
32053226
seq.tkip.iv32, p1k, 0, key_offset);
32063227
break;
32073228
case WLAN_CIPHER_SUITE_CCMP:
32083229
case WLAN_CIPHER_SUITE_WEP40:
32093230
case WLAN_CIPHER_SUITE_WEP104:
32103231
case WLAN_CIPHER_SUITE_GCMP:
32113232
case WLAN_CIPHER_SUITE_GCMP_256:
3212-
ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
3233+
ret = iwl_mvm_send_sta_key(mvm, sta_id, keyconf, mcast,
32133234
0, NULL, 0, key_offset);
32143235
break;
32153236
default:
3216-
ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
3237+
ret = iwl_mvm_send_sta_key(mvm, sta_id, keyconf, mcast,
32173238
0, NULL, 0, key_offset);
32183239
}
32193240

@@ -3234,6 +3255,9 @@ static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id,
32343255
int ret, size;
32353256
u32 status;
32363257

3258+
if (sta_id == IWL_MVM_INVALID_STA)
3259+
return -EINVAL;
3260+
32373261
key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
32383262
STA_KEY_FLG_KEYID_MSK);
32393263
key_flags |= cpu_to_le16(STA_KEY_FLG_NO_ENC | STA_KEY_FLG_WEP_KEY_MAP);
@@ -3277,42 +3301,48 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
32773301
{
32783302
bool mcast = !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE);
32793303
struct iwl_mvm_sta *mvm_sta;
3280-
u8 sta_id;
3304+
u8 sta_id = IWL_MVM_INVALID_STA;
32813305
int ret;
32823306
static const u8 __maybe_unused zero_addr[ETH_ALEN] = {0};
32833307

32843308
lockdep_assert_held(&mvm->mutex);
32853309

3286-
/* Get the station id from the mvm local station table */
3287-
mvm_sta = iwl_mvm_get_key_sta(mvm, vif, sta);
3288-
if (!mvm_sta) {
3289-
IWL_ERR(mvm, "Failed to find station\n");
3290-
return -EINVAL;
3291-
}
3292-
sta_id = mvm_sta->sta_id;
3310+
if (vif->type != NL80211_IFTYPE_AP ||
3311+
keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
3312+
/* Get the station id from the mvm local station table */
3313+
mvm_sta = iwl_mvm_get_key_sta(mvm, vif, sta);
3314+
if (!mvm_sta) {
3315+
IWL_ERR(mvm, "Failed to find station\n");
3316+
return -EINVAL;
3317+
}
3318+
sta_id = mvm_sta->sta_id;
32933319

3294-
if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
3295-
keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
3296-
keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256) {
3297-
ret = iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id, false);
3298-
goto end;
3299-
}
3320+
if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
3321+
keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
3322+
keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256) {
3323+
ret = iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id,
3324+
false);
3325+
goto end;
3326+
}
33003327

3301-
/*
3302-
* It is possible that the 'sta' parameter is NULL, and thus
3303-
* there is a need to retrieve the sta from the local station table.
3304-
*/
3305-
if (!sta) {
3306-
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
3307-
lockdep_is_held(&mvm->mutex));
3308-
if (IS_ERR_OR_NULL(sta)) {
3309-
IWL_ERR(mvm, "Invalid station id\n");
3310-
return -EINVAL;
3328+
/*
3329+
* It is possible that the 'sta' parameter is NULL, and thus
3330+
* there is a need to retrieve the sta from the local station
3331+
* table.
3332+
*/
3333+
if (!sta) {
3334+
sta = rcu_dereference_protected(
3335+
mvm->fw_id_to_mac_id[sta_id],
3336+
lockdep_is_held(&mvm->mutex));
3337+
if (IS_ERR_OR_NULL(sta)) {
3338+
IWL_ERR(mvm, "Invalid station id\n");
3339+
return -EINVAL;
3340+
}
33113341
}
3312-
}
33133342

3314-
if (WARN_ON_ONCE(iwl_mvm_sta_from_mac80211(sta)->vif != vif))
3315-
return -EINVAL;
3343+
if (WARN_ON_ONCE(iwl_mvm_sta_from_mac80211(sta)->vif != vif))
3344+
return -EINVAL;
3345+
}
33163346

33173347
/* If the key_offset is not pre-assigned, we need to find a
33183348
* 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,
33423372
* to the same key slot (offset).
33433373
* If this fails, remove the original as well.
33443374
*/
3345-
if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
3346-
keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) {
3375+
if ((keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
3376+
keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) &&
3377+
sta) {
33473378
ret = __iwl_mvm_set_sta_key(mvm, vif, sta, keyconf,
33483379
key_offset, !mcast);
33493380
if (ret) {
@@ -3377,6 +3408,9 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
33773408
mvm_sta = iwl_mvm_get_key_sta(mvm, vif, sta);
33783409
if (mvm_sta)
33793410
sta_id = mvm_sta->sta_id;
3411+
else if (!sta && vif->type == NL80211_IFTYPE_AP && mcast)
3412+
sta_id = iwl_mvm_vif_from_mac80211(vif)->mcast_sta.sta_id;
3413+
33803414

33813415
IWL_DEBUG_WEP(mvm, "mvm remove dynamic key: idx=%d sta=%d\n",
33823416
keyconf->keyidx, sta_id);
@@ -3399,7 +3433,7 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
33993433
}
34003434
mvm->fw_key_deleted[keyconf->hw_key_idx] = 0;
34013435

3402-
if (!mvm_sta) {
3436+
if (sta && !mvm_sta) {
34033437
IWL_DEBUG_WEP(mvm, "station non-existent, early return.\n");
34043438
return 0;
34053439
}
@@ -3430,7 +3464,7 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,
34303464
mvm_sta = iwl_mvm_get_key_sta(mvm, vif, sta);
34313465
if (WARN_ON_ONCE(!mvm_sta))
34323466
goto unlock;
3433-
iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
3467+
iwl_mvm_send_sta_key(mvm, mvm_sta->sta_id, keyconf, mcast,
34343468
iv32, phase1key, CMD_ASYNC, keyconf->hw_key_idx);
34353469

34363470
unlock:

0 commit comments

Comments
 (0)