@@ -211,7 +211,7 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
211
211
}
212
212
213
213
struct wowlan_key_rsc_tsc_data {
214
- struct iwl_wowlan_rsc_tsc_params_cmd * rsc_tsc ;
214
+ struct iwl_wowlan_rsc_tsc_params_cmd_v4 * rsc_tsc ;
215
215
bool have_rsc_tsc ;
216
216
};
217
217
@@ -327,42 +327,194 @@ static void iwl_mvm_wowlan_get_rsc_tsc_data(struct ieee80211_hw *hw,
327
327
}
328
328
}
329
329
330
+ struct wowlan_key_rsc_v5_data {
331
+ struct iwl_wowlan_rsc_tsc_params_cmd * rsc ;
332
+ bool have_rsc ;
333
+ int gtks ;
334
+ int gtk_ids [4 ];
335
+ };
336
+
337
+ static void iwl_mvm_wowlan_get_rsc_v5_data (struct ieee80211_hw * hw ,
338
+ struct ieee80211_vif * vif ,
339
+ struct ieee80211_sta * sta ,
340
+ struct ieee80211_key_conf * key ,
341
+ void * _data )
342
+ {
343
+ struct iwl_mvm * mvm = IWL_MAC80211_GET_MVM (hw );
344
+ struct wowlan_key_rsc_v5_data * data = _data ;
345
+ struct ieee80211_key_seq seq ;
346
+ __le64 * rsc ;
347
+ int i ;
348
+
349
+ /* only for ciphers that can be PTK/GTK */
350
+ switch (key -> cipher ) {
351
+ default :
352
+ return ;
353
+ case WLAN_CIPHER_SUITE_TKIP :
354
+ case WLAN_CIPHER_SUITE_CCMP :
355
+ case WLAN_CIPHER_SUITE_GCMP :
356
+ case WLAN_CIPHER_SUITE_GCMP_256 :
357
+ break ;
358
+ }
359
+
360
+ if (sta ) {
361
+ rsc = data -> rsc -> ucast_rsc ;
362
+ } else {
363
+ if (WARN_ON (data -> gtks > ARRAY_SIZE (data -> gtk_ids )))
364
+ return ;
365
+ data -> gtk_ids [data -> gtks ] = key -> keyidx ;
366
+ rsc = data -> rsc -> mcast_rsc [data -> gtks % 2 ];
367
+ if (WARN_ON (key -> keyidx >
368
+ ARRAY_SIZE (data -> rsc -> mcast_key_id_map )))
369
+ return ;
370
+ data -> rsc -> mcast_key_id_map [key -> keyidx ] = data -> gtks % 2 ;
371
+ if (data -> gtks >= 2 ) {
372
+ int prev = data -> gtks - 2 ;
373
+ int prev_idx = data -> gtk_ids [prev ];
374
+
375
+ data -> rsc -> mcast_key_id_map [prev_idx ] =
376
+ IWL_MCAST_KEY_MAP_INVALID ;
377
+ }
378
+ data -> gtks ++ ;
379
+ }
380
+
381
+ switch (key -> cipher ) {
382
+ default :
383
+ WARN_ON (1 );
384
+ break ;
385
+ case WLAN_CIPHER_SUITE_TKIP :
386
+
387
+ /*
388
+ * For non-QoS this relies on the fact that both the uCode and
389
+ * mac80211 use TID 0 (as they need to to avoid replay attacks)
390
+ * for checking the IV in the frames.
391
+ */
392
+ for (i = 0 ; i < IWL_MAX_TID_COUNT ; i ++ ) {
393
+ ieee80211_get_key_rx_seq (key , i , & seq );
394
+
395
+ rsc [i ] = cpu_to_le64 (((u64 )seq .tkip .iv32 << 16 ) |
396
+ seq .tkip .iv16 );
397
+ }
398
+
399
+ data -> have_rsc = true;
400
+ break ;
401
+ case WLAN_CIPHER_SUITE_CCMP :
402
+ case WLAN_CIPHER_SUITE_GCMP :
403
+ case WLAN_CIPHER_SUITE_GCMP_256 :
404
+ /*
405
+ * For non-QoS this relies on the fact that both the uCode and
406
+ * mac80211/our RX code use TID 0 for checking the PN.
407
+ */
408
+ if (sta ) {
409
+ struct iwl_mvm_sta * mvmsta ;
410
+ struct iwl_mvm_key_pn * ptk_pn ;
411
+ const u8 * pn ;
412
+
413
+ mvmsta = iwl_mvm_sta_from_mac80211 (sta );
414
+ rcu_read_lock ();
415
+ ptk_pn = rcu_dereference (mvmsta -> ptk_pn [key -> keyidx ]);
416
+ if (WARN_ON (!ptk_pn )) {
417
+ rcu_read_unlock ();
418
+ break ;
419
+ }
420
+
421
+ for (i = 0 ; i < IWL_MAX_TID_COUNT ; i ++ ) {
422
+ pn = iwl_mvm_find_max_pn (key , ptk_pn , & seq , i ,
423
+ mvm -> trans -> num_rx_queues );
424
+ rsc [i ] = cpu_to_le64 ((u64 )pn [5 ] |
425
+ ((u64 )pn [4 ] << 8 ) |
426
+ ((u64 )pn [3 ] << 16 ) |
427
+ ((u64 )pn [2 ] << 24 ) |
428
+ ((u64 )pn [1 ] << 32 ) |
429
+ ((u64 )pn [0 ] << 40 ));
430
+ }
431
+
432
+ rcu_read_unlock ();
433
+ } else {
434
+ for (i = 0 ; i < IWL_MAX_TID_COUNT ; i ++ ) {
435
+ u8 * pn = seq .ccmp .pn ;
436
+
437
+ ieee80211_get_key_rx_seq (key , i , & seq );
438
+ rsc [i ] = cpu_to_le64 ((u64 )pn [5 ] |
439
+ ((u64 )pn [4 ] << 8 ) |
440
+ ((u64 )pn [3 ] << 16 ) |
441
+ ((u64 )pn [2 ] << 24 ) |
442
+ ((u64 )pn [1 ] << 32 ) |
443
+ ((u64 )pn [0 ] << 40 ));
444
+ }
445
+ }
446
+ data -> have_rsc = true;
447
+ break ;
448
+ }
449
+ }
450
+
330
451
static int iwl_mvm_wowlan_config_rsc_tsc (struct iwl_mvm * mvm ,
331
452
struct ieee80211_vif * vif )
332
453
{
333
454
struct iwl_mvm_vif * mvmvif = iwl_mvm_vif_from_mac80211 (vif );
334
455
int ver = iwl_fw_lookup_cmd_ver (mvm -> fw , LONG_GROUP ,
335
456
WOWLAN_TSC_RSC_PARAM ,
336
457
IWL_FW_CMD_VER_UNKNOWN );
337
- struct wowlan_key_rsc_tsc_data data = {};
338
- int size ;
339
458
int ret ;
340
459
341
- data .rsc_tsc = kzalloc (sizeof (* data .rsc_tsc ), GFP_KERNEL );
342
- if (!data .rsc_tsc )
343
- return - ENOMEM ;
460
+ if (ver == 5 ) {
461
+ struct wowlan_key_rsc_v5_data data = {};
462
+ int i ;
463
+
464
+ data .rsc = kmalloc (sizeof (* data .rsc ), GFP_KERNEL );
465
+ if (!data .rsc )
466
+ return - ENOMEM ;
467
+
468
+ memset (data .rsc , 0xff , sizeof (* data .rsc ));
469
+
470
+ for (i = 0 ; i < ARRAY_SIZE (data .rsc -> mcast_key_id_map ); i ++ )
471
+ data .rsc -> mcast_key_id_map [i ] =
472
+ IWL_MCAST_KEY_MAP_INVALID ;
473
+ data .rsc -> sta_id = cpu_to_le32 (mvmvif -> ap_sta_id );
474
+
475
+ ieee80211_iter_keys (mvm -> hw , vif ,
476
+ iwl_mvm_wowlan_get_rsc_v5_data ,
477
+ & data );
478
+
479
+ if (data .have_rsc )
480
+ ret = iwl_mvm_send_cmd_pdu (mvm , WOWLAN_TSC_RSC_PARAM ,
481
+ CMD_ASYNC , sizeof (* data .rsc ),
482
+ data .rsc );
483
+ else
484
+ ret = 0 ;
485
+ kfree (data .rsc );
486
+ } else if (ver == 4 || ver == 2 || ver == IWL_FW_CMD_VER_UNKNOWN ) {
487
+ struct wowlan_key_rsc_tsc_data data = {};
488
+ int size ;
344
489
345
- if (ver == 4 ) {
346
- size = sizeof (* data .rsc_tsc );
347
- data .rsc_tsc -> sta_id = cpu_to_le32 (mvmvif -> ap_sta_id );
348
- } else if (ver == 2 || ver == IWL_FW_CMD_VER_UNKNOWN ) {
349
- size = sizeof (data .rsc_tsc -> params );
490
+ data .rsc_tsc = kzalloc (sizeof (* data .rsc_tsc ), GFP_KERNEL );
491
+ if (!data .rsc_tsc )
492
+ return - ENOMEM ;
493
+
494
+ if (ver == 4 ) {
495
+ size = sizeof (* data .rsc_tsc );
496
+ data .rsc_tsc -> sta_id = cpu_to_le32 (mvmvif -> ap_sta_id );
497
+ } else {
498
+ /* ver == 2 || ver == IWL_FW_CMD_VER_UNKNOWN */
499
+ size = sizeof (data .rsc_tsc -> params );
500
+ }
501
+
502
+ ieee80211_iter_keys (mvm -> hw , vif ,
503
+ iwl_mvm_wowlan_get_rsc_tsc_data ,
504
+ & data );
505
+
506
+ if (data .have_rsc_tsc )
507
+ ret = iwl_mvm_send_cmd_pdu (mvm , WOWLAN_TSC_RSC_PARAM ,
508
+ CMD_ASYNC , size ,
509
+ data .rsc_tsc );
510
+ else
511
+ ret = 0 ;
512
+ kfree (data .rsc_tsc );
350
513
} else {
351
514
ret = 0 ;
352
515
WARN_ON_ONCE (1 );
353
- goto out ;
354
516
}
355
517
356
- ieee80211_iter_keys (mvm -> hw , vif , iwl_mvm_wowlan_get_rsc_tsc_data ,
357
- & data );
358
-
359
- if (data .have_rsc_tsc )
360
- ret = iwl_mvm_send_cmd_pdu (mvm , WOWLAN_TSC_RSC_PARAM ,
361
- CMD_ASYNC , size , data .rsc_tsc );
362
- else
363
- ret = 0 ;
364
- out :
365
- kfree (data .rsc_tsc );
366
518
return ret ;
367
519
}
368
520
0 commit comments