Skip to content

Commit ccdde7c

Browse files
wifi: mac80211: properly implement MLO key handling
Implement key installation and lookup (on TX and RX) for MLO, so we can use multiple GTKs/IGTKs/BIGTKs. Co-authored-by: Ilan Peer <[email protected]> Signed-off-by: Ilan Peer <[email protected]> Signed-off-by: Johannes Berg <[email protected]>
1 parent e7a7b84 commit ccdde7c

File tree

8 files changed

+286
-104
lines changed

8 files changed

+286
-104
lines changed

include/net/mac80211.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1975,6 +1975,7 @@ enum ieee80211_key_flags {
19751975
* - Temporal Authenticator Rx MIC Key (64 bits)
19761976
* @icv_len: The ICV length for this key type
19771977
* @iv_len: The IV length for this key type
1978+
* @link_id: the link ID for MLO, or -1 for non-MLO or pairwise keys
19781979
*/
19791980
struct ieee80211_key_conf {
19801981
atomic64_t tx_pn;
@@ -1984,6 +1985,7 @@ struct ieee80211_key_conf {
19841985
u8 hw_key_idx;
19851986
s8 keyidx;
19861987
u16 flags;
1988+
s8 link_id;
19871989
u8 keylen;
19881990
u8 key[];
19891991
};

net/mac80211/cfg.c

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,18 @@
2424
#include "wme.h"
2525

2626
static struct ieee80211_link_data *
27-
ieee80211_link_or_deflink(struct ieee80211_sub_if_data *sdata, int link_id)
27+
ieee80211_link_or_deflink(struct ieee80211_sub_if_data *sdata, int link_id,
28+
bool require_valid)
2829
{
2930
struct ieee80211_link_data *link;
3031

3132
if (link_id < 0) {
32-
if (sdata->vif.valid_links)
33+
/*
34+
* For keys, if sdata is not an MLD, we might not use
35+
* the return value at all (if it's not a pairwise key),
36+
* so in that case (require_valid==false) don't error.
37+
*/
38+
if (require_valid && sdata->vif.valid_links)
3339
return ERR_PTR(-EINVAL);
3440

3541
return &sdata->deflink;
@@ -456,6 +462,8 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
456462
const u8 *mac_addr, struct key_params *params)
457463
{
458464
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
465+
struct ieee80211_link_data *link =
466+
ieee80211_link_or_deflink(sdata, link_id, false);
459467
struct ieee80211_local *local = sdata->local;
460468
struct sta_info *sta = NULL;
461469
struct ieee80211_key *key;
@@ -464,6 +472,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
464472
if (!ieee80211_sdata_running(sdata))
465473
return -ENETDOWN;
466474

475+
if (IS_ERR(link))
476+
return PTR_ERR(link);
477+
467478
if (pairwise && params->mode == NL80211_KEY_SET_TX)
468479
return ieee80211_set_tx(sdata, mac_addr, key_idx);
469480

@@ -472,6 +483,8 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
472483
case WLAN_CIPHER_SUITE_WEP40:
473484
case WLAN_CIPHER_SUITE_TKIP:
474485
case WLAN_CIPHER_SUITE_WEP104:
486+
if (link_id >= 0)
487+
return -EINVAL;
475488
if (WARN_ON_ONCE(fips_enabled))
476489
return -EINVAL;
477490
break;
@@ -484,6 +497,8 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
484497
if (IS_ERR(key))
485498
return PTR_ERR(key);
486499

500+
key->conf.link_id = link_id;
501+
487502
if (pairwise)
488503
key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE;
489504

@@ -545,7 +560,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
545560
break;
546561
}
547562

548-
err = ieee80211_key_link(key, sdata, sta);
563+
err = ieee80211_key_link(key, link, sta);
549564

550565
out_unlock:
551566
mutex_unlock(&local->sta_mtx);
@@ -554,18 +569,37 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
554569
}
555570

556571
static struct ieee80211_key *
557-
ieee80211_lookup_key(struct ieee80211_sub_if_data *sdata,
572+
ieee80211_lookup_key(struct ieee80211_sub_if_data *sdata, int link_id,
558573
u8 key_idx, bool pairwise, const u8 *mac_addr)
559574
{
560575
struct ieee80211_local *local = sdata->local;
576+
struct ieee80211_link_data *link = &sdata->deflink;
561577
struct ieee80211_key *key;
562-
struct sta_info *sta;
578+
579+
if (link_id >= 0) {
580+
link = rcu_dereference_check(sdata->link[link_id],
581+
lockdep_is_held(&sdata->wdev.mtx));
582+
if (!link)
583+
return NULL;
584+
}
563585

564586
if (mac_addr) {
587+
struct sta_info *sta;
588+
struct link_sta_info *link_sta;
589+
565590
sta = sta_info_get_bss(sdata, mac_addr);
566591
if (!sta)
567592
return NULL;
568593

594+
if (link_id >= 0) {
595+
link_sta = rcu_dereference_check(sta->link[link_id],
596+
lockdep_is_held(&local->sta_mtx));
597+
if (!link_sta)
598+
return NULL;
599+
} else {
600+
link_sta = &sta->deflink;
601+
}
602+
569603
if (pairwise && key_idx < NUM_DEFAULT_KEYS)
570604
return rcu_dereference_check_key_mtx(local,
571605
sta->ptk[key_idx]);
@@ -575,7 +609,7 @@ ieee80211_lookup_key(struct ieee80211_sub_if_data *sdata,
575609
NUM_DEFAULT_MGMT_KEYS +
576610
NUM_DEFAULT_BEACON_KEYS)
577611
return rcu_dereference_check_key_mtx(local,
578-
sta->deflink.gtk[key_idx]);
612+
link_sta->gtk[key_idx]);
579613

580614
return NULL;
581615
}
@@ -584,7 +618,7 @@ ieee80211_lookup_key(struct ieee80211_sub_if_data *sdata,
584618
return rcu_dereference_check_key_mtx(local,
585619
sdata->keys[key_idx]);
586620

587-
key = rcu_dereference_check_key_mtx(local, sdata->deflink.gtk[key_idx]);
621+
key = rcu_dereference_check_key_mtx(local, link->gtk[key_idx]);
588622
if (key)
589623
return key;
590624

@@ -607,7 +641,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
607641
mutex_lock(&local->sta_mtx);
608642
mutex_lock(&local->key_mtx);
609643

610-
key = ieee80211_lookup_key(sdata, key_idx, pairwise, mac_addr);
644+
key = ieee80211_lookup_key(sdata, link_id, key_idx, pairwise, mac_addr);
611645
if (!key) {
612646
ret = -ENOENT;
613647
goto out_unlock;
@@ -643,7 +677,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
643677

644678
rcu_read_lock();
645679

646-
key = ieee80211_lookup_key(sdata, key_idx, pairwise, mac_addr);
680+
key = ieee80211_lookup_key(sdata, link_id, key_idx, pairwise, mac_addr);
647681
if (!key)
648682
goto out;
649683

@@ -734,8 +768,13 @@ static int ieee80211_config_default_key(struct wiphy *wiphy,
734768
bool multi)
735769
{
736770
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
771+
struct ieee80211_link_data *link =
772+
ieee80211_link_or_deflink(sdata, link_id, false);
737773

738-
ieee80211_set_default_key(sdata, key_idx, uni, multi);
774+
if (IS_ERR(link))
775+
return PTR_ERR(link);
776+
777+
ieee80211_set_default_key(link, key_idx, uni, multi);
739778

740779
return 0;
741780
}
@@ -745,8 +784,13 @@ static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy,
745784
int link_id, u8 key_idx)
746785
{
747786
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
787+
struct ieee80211_link_data *link =
788+
ieee80211_link_or_deflink(sdata, link_id, true);
748789

749-
ieee80211_set_default_mgmt_key(sdata, key_idx);
790+
if (IS_ERR(link))
791+
return PTR_ERR(link);
792+
793+
ieee80211_set_default_mgmt_key(link, key_idx);
750794

751795
return 0;
752796
}
@@ -756,8 +800,13 @@ static int ieee80211_config_default_beacon_key(struct wiphy *wiphy,
756800
int link_id, u8 key_idx)
757801
{
758802
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
803+
struct ieee80211_link_data *link =
804+
ieee80211_link_or_deflink(sdata, link_id, true);
805+
806+
if (IS_ERR(link))
807+
return PTR_ERR(link);
759808

760-
ieee80211_set_default_beacon_key(sdata, key_idx);
809+
ieee80211_set_default_beacon_key(link, key_idx);
761810

762811
return 0;
763812
}
@@ -2588,7 +2637,7 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy,
25882637
struct ieee80211_local *local = wiphy_priv(wiphy);
25892638
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
25902639
struct ieee80211_link_data *link =
2591-
ieee80211_link_or_deflink(sdata, params->link_id);
2640+
ieee80211_link_or_deflink(sdata, params->link_id, true);
25922641
struct ieee80211_tx_queue_params p;
25932642

25942643
if (!local->ops->conf_tx)

net/mac80211/ieee80211_i.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ struct ieee80211_rx_data {
213213
struct ieee80211_sub_if_data *sdata;
214214
struct ieee80211_link_data *link;
215215
struct sta_info *sta;
216+
struct link_sta_info *link_sta;
216217
struct ieee80211_key *key;
217218

218219
unsigned int flags;

net/mac80211/iface.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,10 +434,19 @@ struct link_container {
434434
static void ieee80211_free_links(struct ieee80211_sub_if_data *sdata,
435435
struct link_container **links)
436436
{
437+
LIST_HEAD(keys);
437438
unsigned int link_id;
438439

440+
for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
441+
if (!links[link_id])
442+
continue;
443+
ieee80211_remove_link_keys(&links[link_id]->data, &keys);
444+
}
445+
439446
synchronize_rcu();
440447

448+
ieee80211_free_key_list(sdata->local, &keys);
449+
441450
for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
442451
if (!links[link_id])
443452
continue;

0 commit comments

Comments
 (0)