@@ -2980,7 +2980,7 @@ static struct iwl_mvm_sta *iwl_mvm_get_key_sta(struct iwl_mvm *mvm,
2980
2980
}
2981
2981
2982
2982
static int iwl_mvm_send_sta_key (struct iwl_mvm * mvm ,
2983
- struct iwl_mvm_sta * mvm_sta ,
2983
+ u32 sta_id ,
2984
2984
struct ieee80211_key_conf * key , bool mcast ,
2985
2985
u32 tkip_iv32 , u16 * tkip_p1k , u32 cmd_flags ,
2986
2986
u8 key_offset )
@@ -2998,6 +2998,9 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
2998
2998
bool new_api = fw_has_api (& mvm -> fw -> ucode_capa ,
2999
2999
IWL_UCODE_TLV_API_TKIP_MIC_KEYS );
3000
3000
3001
+ if (sta_id == IWL_MVM_INVALID_STA )
3002
+ return - EINVAL ;
3003
+
3001
3004
keyidx = (key -> keyidx << STA_KEY_FLG_KEYID_POS ) &
3002
3005
STA_KEY_FLG_KEYID_MSK ;
3003
3006
key_flags = cpu_to_le16 (keyidx );
@@ -3056,7 +3059,7 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
3056
3059
3057
3060
u .cmd .common .key_offset = key_offset ;
3058
3061
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 ;
3060
3063
3061
3064
if (new_api ) {
3062
3065
u .cmd .transmit_seq_cnt = cpu_to_le64 (pn );
@@ -3189,31 +3192,49 @@ static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
3189
3192
u8 key_offset ,
3190
3193
bool mcast )
3191
3194
{
3192
- struct iwl_mvm_sta * mvm_sta = iwl_mvm_sta_from_mac80211 (sta );
3193
3195
int ret ;
3194
3196
const u8 * addr ;
3195
3197
struct ieee80211_key_seq seq ;
3196
3198
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
+ }
3197
3214
3198
3215
switch (keyconf -> cipher ) {
3199
3216
case WLAN_CIPHER_SUITE_TKIP :
3217
+ if (vif -> type == NL80211_IFTYPE_AP ) {
3218
+ ret = - EINVAL ;
3219
+ break ;
3220
+ }
3200
3221
addr = iwl_mvm_get_mac_addr (mvm , vif , sta );
3201
3222
/* get phase 1 key from mac80211 */
3202
3223
ieee80211_get_key_rx_seq (keyconf , 0 , & seq );
3203
3224
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 ,
3205
3226
seq .tkip .iv32 , p1k , 0 , key_offset );
3206
3227
break ;
3207
3228
case WLAN_CIPHER_SUITE_CCMP :
3208
3229
case WLAN_CIPHER_SUITE_WEP40 :
3209
3230
case WLAN_CIPHER_SUITE_WEP104 :
3210
3231
case WLAN_CIPHER_SUITE_GCMP :
3211
3232
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 ,
3213
3234
0 , NULL , 0 , key_offset );
3214
3235
break ;
3215
3236
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 ,
3217
3238
0 , NULL , 0 , key_offset );
3218
3239
}
3219
3240
@@ -3234,6 +3255,9 @@ static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id,
3234
3255
int ret , size ;
3235
3256
u32 status ;
3236
3257
3258
+ if (sta_id == IWL_MVM_INVALID_STA )
3259
+ return - EINVAL ;
3260
+
3237
3261
key_flags = cpu_to_le16 ((keyconf -> keyidx << STA_KEY_FLG_KEYID_POS ) &
3238
3262
STA_KEY_FLG_KEYID_MSK );
3239
3263
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,
3277
3301
{
3278
3302
bool mcast = !(keyconf -> flags & IEEE80211_KEY_FLAG_PAIRWISE );
3279
3303
struct iwl_mvm_sta * mvm_sta ;
3280
- u8 sta_id ;
3304
+ u8 sta_id = IWL_MVM_INVALID_STA ;
3281
3305
int ret ;
3282
3306
static const u8 __maybe_unused zero_addr [ETH_ALEN ] = {0 };
3283
3307
3284
3308
lockdep_assert_held (& mvm -> mutex );
3285
3309
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 ;
3293
3319
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
+ }
3300
3327
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
+ }
3311
3341
}
3312
- }
3313
3342
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
+ }
3316
3346
3317
3347
/* If the key_offset is not pre-assigned, we need to find a
3318
3348
* 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
3372
* to the same key slot (offset).
3343
3373
* If this fails, remove the original as well.
3344
3374
*/
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 ) {
3347
3378
ret = __iwl_mvm_set_sta_key (mvm , vif , sta , keyconf ,
3348
3379
key_offset , !mcast );
3349
3380
if (ret ) {
@@ -3377,6 +3408,9 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
3377
3408
mvm_sta = iwl_mvm_get_key_sta (mvm , vif , sta );
3378
3409
if (mvm_sta )
3379
3410
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
+
3380
3414
3381
3415
IWL_DEBUG_WEP (mvm , "mvm remove dynamic key: idx=%d sta=%d\n" ,
3382
3416
keyconf -> keyidx , sta_id );
@@ -3399,7 +3433,7 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
3399
3433
}
3400
3434
mvm -> fw_key_deleted [keyconf -> hw_key_idx ] = 0 ;
3401
3435
3402
- if (!mvm_sta ) {
3436
+ if (sta && !mvm_sta ) {
3403
3437
IWL_DEBUG_WEP (mvm , "station non-existent, early return.\n" );
3404
3438
return 0 ;
3405
3439
}
@@ -3430,7 +3464,7 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,
3430
3464
mvm_sta = iwl_mvm_get_key_sta (mvm , vif , sta );
3431
3465
if (WARN_ON_ONCE (!mvm_sta ))
3432
3466
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 ,
3434
3468
iv32 , phase1key , CMD_ASYNC , keyconf -> hw_key_idx );
3435
3469
3436
3470
unlock :
0 commit comments