Commit e5473e80 authored by Jouni Malinen's avatar Jouni Malinen Committed by Johannes Berg

mac80211: Support BIGTK configuration for Beacon protection

Extend mac80211 key configuration to support the new BIGTK with key
index values 6 and 7. Support for actually protecting Beacon frames
(adding the MME in AP mode and checking it in STA mode) is covered in
separate commits.
Signed-off-by: default avatarJouni Malinen <jouni@codeaurora.org>
Link: https://lore.kernel.org/r/20200222132548.20835-3-jouni@codeaurora.orgSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 56be393f
...@@ -568,7 +568,8 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, ...@@ -568,7 +568,8 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
if (pairwise && key_idx < NUM_DEFAULT_KEYS) if (pairwise && key_idx < NUM_DEFAULT_KEYS)
key = rcu_dereference(sta->ptk[key_idx]); key = rcu_dereference(sta->ptk[key_idx]);
else if (!pairwise && else if (!pairwise &&
key_idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) key_idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS +
NUM_DEFAULT_BEACON_KEYS)
key = rcu_dereference(sta->gtk[key_idx]); key = rcu_dereference(sta->gtk[key_idx]);
} else } else
key = rcu_dereference(sdata->keys[key_idx]); key = rcu_dereference(sdata->keys[key_idx]);
...@@ -680,6 +681,17 @@ static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy, ...@@ -680,6 +681,17 @@ static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy,
return 0; return 0;
} }
static int ieee80211_config_default_beacon_key(struct wiphy *wiphy,
struct net_device *dev,
u8 key_idx)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
ieee80211_set_default_beacon_key(sdata, key_idx);
return 0;
}
void sta_set_rate_info_tx(struct sta_info *sta, void sta_set_rate_info_tx(struct sta_info *sta,
const struct ieee80211_tx_rate *rate, const struct ieee80211_tx_rate *rate,
struct rate_info *rinfo) struct rate_info *rinfo)
...@@ -3885,6 +3897,7 @@ const struct cfg80211_ops mac80211_config_ops = { ...@@ -3885,6 +3897,7 @@ const struct cfg80211_ops mac80211_config_ops = {
.get_key = ieee80211_get_key, .get_key = ieee80211_get_key,
.set_default_key = ieee80211_config_default_key, .set_default_key = ieee80211_config_default_key,
.set_default_mgmt_key = ieee80211_config_default_mgmt_key, .set_default_mgmt_key = ieee80211_config_default_mgmt_key,
.set_default_beacon_key = ieee80211_config_default_beacon_key,
.start_ap = ieee80211_start_ap, .start_ap = ieee80211_start_ap,
.change_beacon = ieee80211_change_beacon, .change_beacon = ieee80211_change_beacon,
.stop_ap = ieee80211_stop_ap, .stop_ap = ieee80211_stop_ap,
......
...@@ -433,6 +433,37 @@ void ieee80211_debugfs_key_remove_mgmt_default(struct ieee80211_sub_if_data *sda ...@@ -433,6 +433,37 @@ void ieee80211_debugfs_key_remove_mgmt_default(struct ieee80211_sub_if_data *sda
sdata->debugfs.default_mgmt_key = NULL; sdata->debugfs.default_mgmt_key = NULL;
} }
void
ieee80211_debugfs_key_add_beacon_default(struct ieee80211_sub_if_data *sdata)
{
char buf[50];
struct ieee80211_key *key;
if (!sdata->vif.debugfs_dir)
return;
key = key_mtx_dereference(sdata->local,
sdata->default_beacon_key);
if (key) {
sprintf(buf, "../keys/%d", key->debugfs.cnt);
sdata->debugfs.default_beacon_key =
debugfs_create_symlink("default_beacon_key",
sdata->vif.debugfs_dir, buf);
} else {
ieee80211_debugfs_key_remove_beacon_default(sdata);
}
}
void
ieee80211_debugfs_key_remove_beacon_default(struct ieee80211_sub_if_data *sdata)
{
if (!sdata)
return;
debugfs_remove(sdata->debugfs.default_beacon_key);
sdata->debugfs.default_beacon_key = NULL;
}
void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
struct sta_info *sta) struct sta_info *sta)
{ {
......
...@@ -10,6 +10,10 @@ void ieee80211_debugfs_key_add_mgmt_default( ...@@ -10,6 +10,10 @@ void ieee80211_debugfs_key_add_mgmt_default(
struct ieee80211_sub_if_data *sdata); struct ieee80211_sub_if_data *sdata);
void ieee80211_debugfs_key_remove_mgmt_default( void ieee80211_debugfs_key_remove_mgmt_default(
struct ieee80211_sub_if_data *sdata); struct ieee80211_sub_if_data *sdata);
void ieee80211_debugfs_key_add_beacon_default(
struct ieee80211_sub_if_data *sdata);
void ieee80211_debugfs_key_remove_beacon_default(
struct ieee80211_sub_if_data *sdata);
void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
struct sta_info *sta); struct sta_info *sta);
#else #else
...@@ -26,6 +30,12 @@ static inline void ieee80211_debugfs_key_add_mgmt_default( ...@@ -26,6 +30,12 @@ static inline void ieee80211_debugfs_key_add_mgmt_default(
static inline void ieee80211_debugfs_key_remove_mgmt_default( static inline void ieee80211_debugfs_key_remove_mgmt_default(
struct ieee80211_sub_if_data *sdata) struct ieee80211_sub_if_data *sdata)
{} {}
static inline void ieee80211_debugfs_key_add_beacon_default(
struct ieee80211_sub_if_data *sdata)
{}
static inline void ieee80211_debugfs_key_remove_beacon_default(
struct ieee80211_sub_if_data *sdata)
{}
static inline void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, static inline void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
struct sta_info *sta) struct sta_info *sta)
{} {}
......
...@@ -901,10 +901,13 @@ struct ieee80211_sub_if_data { ...@@ -901,10 +901,13 @@ struct ieee80211_sub_if_data {
/* bit field of ACM bits (BIT(802.1D tag)) */ /* bit field of ACM bits (BIT(802.1D tag)) */
u8 wmm_acm; u8 wmm_acm;
struct ieee80211_key __rcu *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; struct ieee80211_key __rcu *keys[NUM_DEFAULT_KEYS +
NUM_DEFAULT_MGMT_KEYS +
NUM_DEFAULT_BEACON_KEYS];
struct ieee80211_key __rcu *default_unicast_key; struct ieee80211_key __rcu *default_unicast_key;
struct ieee80211_key __rcu *default_multicast_key; struct ieee80211_key __rcu *default_multicast_key;
struct ieee80211_key __rcu *default_mgmt_key; struct ieee80211_key __rcu *default_mgmt_key;
struct ieee80211_key __rcu *default_beacon_key;
u16 sequence_number; u16 sequence_number;
__be16 control_port_protocol; __be16 control_port_protocol;
...@@ -978,6 +981,7 @@ struct ieee80211_sub_if_data { ...@@ -978,6 +981,7 @@ struct ieee80211_sub_if_data {
struct dentry *default_unicast_key; struct dentry *default_unicast_key;
struct dentry *default_multicast_key; struct dentry *default_multicast_key;
struct dentry *default_mgmt_key; struct dentry *default_mgmt_key;
struct dentry *default_beacon_key;
} debugfs; } debugfs;
#endif #endif
......
...@@ -407,6 +407,31 @@ void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, ...@@ -407,6 +407,31 @@ void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
mutex_unlock(&sdata->local->key_mtx); mutex_unlock(&sdata->local->key_mtx);
} }
static void
__ieee80211_set_default_beacon_key(struct ieee80211_sub_if_data *sdata, int idx)
{
struct ieee80211_key *key = NULL;
assert_key_lock(sdata->local);
if (idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS &&
idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS +
NUM_DEFAULT_BEACON_KEYS)
key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
rcu_assign_pointer(sdata->default_beacon_key, key);
ieee80211_debugfs_key_update_default(sdata);
}
void ieee80211_set_default_beacon_key(struct ieee80211_sub_if_data *sdata,
int idx)
{
mutex_lock(&sdata->local->key_mtx);
__ieee80211_set_default_beacon_key(sdata, idx);
mutex_unlock(&sdata->local->key_mtx);
}
static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta, struct sta_info *sta,
bool pairwise, bool pairwise,
...@@ -415,7 +440,7 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, ...@@ -415,7 +440,7 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
{ {
int idx; int idx;
int ret = 0; int ret = 0;
bool defunikey, defmultikey, defmgmtkey; bool defunikey, defmultikey, defmgmtkey, defbeaconkey;
/* caller must provide at least one old/new */ /* caller must provide at least one old/new */
if (WARN_ON(!new && !old)) if (WARN_ON(!new && !old))
...@@ -480,6 +505,9 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, ...@@ -480,6 +505,9 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
defmgmtkey = old && defmgmtkey = old &&
old == key_mtx_dereference(sdata->local, old == key_mtx_dereference(sdata->local,
sdata->default_mgmt_key); sdata->default_mgmt_key);
defbeaconkey = old &&
old == key_mtx_dereference(sdata->local,
sdata->default_beacon_key);
if (defunikey && !new) if (defunikey && !new)
__ieee80211_set_default_key(sdata, -1, true, false); __ieee80211_set_default_key(sdata, -1, true, false);
...@@ -487,6 +515,8 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, ...@@ -487,6 +515,8 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
__ieee80211_set_default_key(sdata, -1, false, true); __ieee80211_set_default_key(sdata, -1, false, true);
if (defmgmtkey && !new) if (defmgmtkey && !new)
__ieee80211_set_default_mgmt_key(sdata, -1); __ieee80211_set_default_mgmt_key(sdata, -1);
if (defbeaconkey && !new)
__ieee80211_set_default_beacon_key(sdata, -1);
rcu_assign_pointer(sdata->keys[idx], new); rcu_assign_pointer(sdata->keys[idx], new);
if (defunikey && new) if (defunikey && new)
...@@ -498,6 +528,9 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, ...@@ -498,6 +528,9 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
if (defmgmtkey && new) if (defmgmtkey && new)
__ieee80211_set_default_mgmt_key(sdata, __ieee80211_set_default_mgmt_key(sdata,
new->conf.keyidx); new->conf.keyidx);
if (defbeaconkey && new)
__ieee80211_set_default_beacon_key(sdata,
new->conf.keyidx);
} }
if (old) if (old)
...@@ -515,7 +548,9 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, ...@@ -515,7 +548,9 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
struct ieee80211_key *key; struct ieee80211_key *key;
int i, j, err; int i, j, err;
if (WARN_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)) if (WARN_ON(idx < 0 ||
idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS +
NUM_DEFAULT_BEACON_KEYS))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL); key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL);
...@@ -978,6 +1013,7 @@ static void ieee80211_free_keys_iface(struct ieee80211_sub_if_data *sdata, ...@@ -978,6 +1013,7 @@ static void ieee80211_free_keys_iface(struct ieee80211_sub_if_data *sdata,
sdata->crypto_tx_tailroom_pending_dec = 0; sdata->crypto_tx_tailroom_pending_dec = 0;
ieee80211_debugfs_key_remove_mgmt_default(sdata); ieee80211_debugfs_key_remove_mgmt_default(sdata);
ieee80211_debugfs_key_remove_beacon_default(sdata);
list_for_each_entry_safe(key, tmp, &sdata->key_list, list) { list_for_each_entry_safe(key, tmp, &sdata->key_list, list) {
ieee80211_key_replace(key->sdata, key->sta, ieee80211_key_replace(key->sdata, key->sta,
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#define NUM_DEFAULT_KEYS 4 #define NUM_DEFAULT_KEYS 4
#define NUM_DEFAULT_MGMT_KEYS 2 #define NUM_DEFAULT_MGMT_KEYS 2
#define NUM_DEFAULT_BEACON_KEYS 2
#define INVALID_PTK_KEYIDX 2 /* Keyidx always pointing to a NULL key for PTK */ #define INVALID_PTK_KEYIDX 2 /* Keyidx always pointing to a NULL key for PTK */
struct ieee80211_local; struct ieee80211_local;
...@@ -153,6 +154,8 @@ void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx, ...@@ -153,6 +154,8 @@ void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx,
bool uni, bool multi); bool uni, bool multi);
void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
int idx); int idx);
void ieee80211_set_default_beacon_key(struct ieee80211_sub_if_data *sdata,
int idx);
void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata, void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata,
bool force_synchronize); bool force_synchronize);
void ieee80211_free_sta_keys(struct ieee80211_local *local, void ieee80211_free_sta_keys(struct ieee80211_local *local,
......
...@@ -533,7 +533,9 @@ struct sta_info { ...@@ -533,7 +533,9 @@ struct sta_info {
u8 addr[ETH_ALEN]; u8 addr[ETH_ALEN];
struct ieee80211_local *local; struct ieee80211_local *local;
struct ieee80211_sub_if_data *sdata; struct ieee80211_sub_if_data *sdata;
struct ieee80211_key __rcu *gtk[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; struct ieee80211_key __rcu *gtk[NUM_DEFAULT_KEYS +
NUM_DEFAULT_MGMT_KEYS +
NUM_DEFAULT_BEACON_KEYS];
struct ieee80211_key __rcu *ptk[NUM_DEFAULT_KEYS]; struct ieee80211_key __rcu *ptk[NUM_DEFAULT_KEYS];
u8 ptk_idx; u8 ptk_idx;
struct rate_control_ref *rate_ctrl; struct rate_control_ref *rate_ctrl;
......
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