forked from mirrors/linux
		
	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: Jouni Malinen <jouni@codeaurora.org> Link: https://lore.kernel.org/r/20200222132548.20835-3-jouni@codeaurora.org Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
		
							parent
							
								
									56be393fa8
								
							
						
					
					
						commit
						e5473e80d4
					
				
					 7 changed files with 104 additions and 5 deletions
				
			
		| 
						 | 
				
			
			@ -568,7 +568,8 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
 | 
			
		|||
		if (pairwise && key_idx < NUM_DEFAULT_KEYS)
 | 
			
		||||
			key = rcu_dereference(sta->ptk[key_idx]);
 | 
			
		||||
		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]);
 | 
			
		||||
	} else
 | 
			
		||||
		key = rcu_dereference(sdata->keys[key_idx]);
 | 
			
		||||
| 
						 | 
				
			
			@ -680,6 +681,17 @@ static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy,
 | 
			
		|||
	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,
 | 
			
		||||
			  const struct ieee80211_tx_rate *rate,
 | 
			
		||||
			  struct rate_info *rinfo)
 | 
			
		||||
| 
						 | 
				
			
			@ -3885,6 +3897,7 @@ const struct cfg80211_ops mac80211_config_ops = {
 | 
			
		|||
	.get_key = ieee80211_get_key,
 | 
			
		||||
	.set_default_key = ieee80211_config_default_key,
 | 
			
		||||
	.set_default_mgmt_key = ieee80211_config_default_mgmt_key,
 | 
			
		||||
	.set_default_beacon_key = ieee80211_config_default_beacon_key,
 | 
			
		||||
	.start_ap = ieee80211_start_ap,
 | 
			
		||||
	.change_beacon = ieee80211_change_beacon,
 | 
			
		||||
	.stop_ap = ieee80211_stop_ap,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -433,6 +433,37 @@ void ieee80211_debugfs_key_remove_mgmt_default(struct ieee80211_sub_if_data *sda
 | 
			
		|||
	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,
 | 
			
		||||
				   struct sta_info *sta)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,10 @@ void ieee80211_debugfs_key_add_mgmt_default(
 | 
			
		|||
	struct ieee80211_sub_if_data *sdata);
 | 
			
		||||
void ieee80211_debugfs_key_remove_mgmt_default(
 | 
			
		||||
	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,
 | 
			
		||||
				   struct sta_info *sta);
 | 
			
		||||
#else
 | 
			
		||||
| 
						 | 
				
			
			@ -26,6 +30,12 @@ static inline void ieee80211_debugfs_key_add_mgmt_default(
 | 
			
		|||
static inline void ieee80211_debugfs_key_remove_mgmt_default(
 | 
			
		||||
	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,
 | 
			
		||||
						 struct sta_info *sta)
 | 
			
		||||
{}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -901,10 +901,13 @@ struct ieee80211_sub_if_data {
 | 
			
		|||
	/* bit field of ACM bits (BIT(802.1D tag)) */
 | 
			
		||||
	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_multicast_key;
 | 
			
		||||
	struct ieee80211_key __rcu *default_mgmt_key;
 | 
			
		||||
	struct ieee80211_key __rcu *default_beacon_key;
 | 
			
		||||
 | 
			
		||||
	u16 sequence_number;
 | 
			
		||||
	__be16 control_port_protocol;
 | 
			
		||||
| 
						 | 
				
			
			@ -978,6 +981,7 @@ struct ieee80211_sub_if_data {
 | 
			
		|||
		struct dentry *default_unicast_key;
 | 
			
		||||
		struct dentry *default_multicast_key;
 | 
			
		||||
		struct dentry *default_mgmt_key;
 | 
			
		||||
		struct dentry *default_beacon_key;
 | 
			
		||||
	} debugfs;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -407,6 +407,31 @@ void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
 | 
			
		|||
	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,
 | 
			
		||||
				  struct sta_info *sta,
 | 
			
		||||
				  bool pairwise,
 | 
			
		||||
| 
						 | 
				
			
			@ -415,7 +440,7 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
 | 
			
		|||
{
 | 
			
		||||
	int idx;
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
	bool defunikey, defmultikey, defmgmtkey;
 | 
			
		||||
	bool defunikey, defmultikey, defmgmtkey, defbeaconkey;
 | 
			
		||||
 | 
			
		||||
	/* caller must provide at least one old/new */
 | 
			
		||||
	if (WARN_ON(!new && !old))
 | 
			
		||||
| 
						 | 
				
			
			@ -480,6 +505,9 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
 | 
			
		|||
		defmgmtkey = old &&
 | 
			
		||||
			old == key_mtx_dereference(sdata->local,
 | 
			
		||||
						sdata->default_mgmt_key);
 | 
			
		||||
		defbeaconkey = old &&
 | 
			
		||||
			old == key_mtx_dereference(sdata->local,
 | 
			
		||||
						   sdata->default_beacon_key);
 | 
			
		||||
 | 
			
		||||
		if (defunikey && !new)
 | 
			
		||||
			__ieee80211_set_default_key(sdata, -1, true, false);
 | 
			
		||||
| 
						 | 
				
			
			@ -487,6 +515,8 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
 | 
			
		|||
			__ieee80211_set_default_key(sdata, -1, false, true);
 | 
			
		||||
		if (defmgmtkey && !new)
 | 
			
		||||
			__ieee80211_set_default_mgmt_key(sdata, -1);
 | 
			
		||||
		if (defbeaconkey && !new)
 | 
			
		||||
			__ieee80211_set_default_beacon_key(sdata, -1);
 | 
			
		||||
 | 
			
		||||
		rcu_assign_pointer(sdata->keys[idx], new);
 | 
			
		||||
		if (defunikey && new)
 | 
			
		||||
| 
						 | 
				
			
			@ -498,6 +528,9 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
 | 
			
		|||
		if (defmgmtkey && new)
 | 
			
		||||
			__ieee80211_set_default_mgmt_key(sdata,
 | 
			
		||||
							 new->conf.keyidx);
 | 
			
		||||
		if (defbeaconkey && new)
 | 
			
		||||
			__ieee80211_set_default_beacon_key(sdata,
 | 
			
		||||
							   new->conf.keyidx);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (old)
 | 
			
		||||
| 
						 | 
				
			
			@ -515,7 +548,9 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
 | 
			
		|||
	struct ieee80211_key *key;
 | 
			
		||||
	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);
 | 
			
		||||
 | 
			
		||||
	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,
 | 
			
		|||
	sdata->crypto_tx_tailroom_pending_dec = 0;
 | 
			
		||||
 | 
			
		||||
	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) {
 | 
			
		||||
		ieee80211_key_replace(key->sdata, key->sta,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,6 +17,7 @@
 | 
			
		|||
 | 
			
		||||
#define NUM_DEFAULT_KEYS 4
 | 
			
		||||
#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 */
 | 
			
		||||
 | 
			
		||||
struct ieee80211_local;
 | 
			
		||||
| 
						 | 
				
			
			@ -153,6 +154,8 @@ void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx,
 | 
			
		|||
			       bool uni, bool multi);
 | 
			
		||||
void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
 | 
			
		||||
				    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,
 | 
			
		||||
			 bool force_synchronize);
 | 
			
		||||
void ieee80211_free_sta_keys(struct ieee80211_local *local,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -533,7 +533,9 @@ struct sta_info {
 | 
			
		|||
	u8 addr[ETH_ALEN];
 | 
			
		||||
	struct ieee80211_local *local;
 | 
			
		||||
	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];
 | 
			
		||||
	u8 ptk_idx;
 | 
			
		||||
	struct rate_control_ref *rate_ctrl;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue