key.c revision b5c34f662a3519d34f9634a14d8de638fdbe0ca3
11f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg/*
21f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg * Copyright 2002-2005, Instant802 Networks, Inc.
31f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg * Copyright 2005-2006, Devicescape Software, Inc.
41f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
53b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * Copyright 2007-2008	Johannes Berg <johannes@sipsolutions.net>
61f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg *
71f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg * This program is free software; you can redistribute it and/or modify
81f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg * it under the terms of the GNU General Public License version 2 as
91f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg * published by the Free Software Foundation.
101f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg */
111f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg
1211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg#include <linux/if_ether.h>
1311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg#include <linux/etherdevice.h>
1411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg#include <linux/list.h>
15d4e46a3d9869563c6210b01bb651c40cbe65da80Johannes Berg#include <linux/rcupdate.h>
16db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg#include <linux/rtnetlink.h>
175a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
181f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg#include <net/mac80211.h>
191f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg#include "ieee80211_i.h"
202448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg#include "driver-ops.h"
211f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg#include "debugfs_key.h"
221f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg#include "aes_ccm.h"
233cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen#include "aes_cmac.h"
241f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg
2511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
26dbbea6713d6096cd1c411cb453a6b71292c78b33Johannes Berg/**
27dbbea6713d6096cd1c411cb453a6b71292c78b33Johannes Berg * DOC: Key handling basics
2811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg *
2911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * Key handling in mac80211 is done based on per-interface (sub_if_data)
3011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * keys and per-station keys. Since each station belongs to an interface,
3111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * each station key also belongs to that interface.
3211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg *
33b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * Hardware acceleration is done on a best-effort basis for algorithms
34b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * that are implemented in software,  for each key the hardware is asked
35b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * to enable that key for offloading but if it cannot do that the key is
36b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * simply kept for software encryption (unless it is for an algorithm
37b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * that isn't implemented in software).
38b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * There is currently no way of knowing whether a key is handled in SW
39b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * or HW except by looking into debugfs.
4011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg *
41b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * All key management is internally protected by a mutex. Within all
42b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * other parts of mac80211, key references are, just as STA structure
43b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * references, protected by RCU. Note, however, that some things are
44b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * unprotected, namely the key->sta dereferences within the hardware
45b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * acceleration functions. This means that sta_info_destroy() must
46b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * remove the key which waits for an RCU grace period.
4711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg */
4811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
4911a843b7e16062389c53ba393c7913956e034eb2Johannes Bergstatic const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
5011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
51ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Bergstatic void assert_key_lock(struct ieee80211_local *local)
523b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{
5346a5ebaf02d69e26ee0f47a0b8d2d9bc619240d4Johannes Berg	lockdep_assert_held(&local->key_mtx);
543b96766f0e643f52ae19e134664df6730c737e87Johannes Berg}
553b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
56dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Bergstatic struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key)
5711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg{
5811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	if (key->sta)
59dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg		return &key->sta->sta;
6011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
61dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	return NULL;
6211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg}
6311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
643ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Bergstatic int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
6511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg{
66dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	struct ieee80211_sub_if_data *sdata;
67dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	struct ieee80211_sta *sta;
6811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	int ret;
6911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
703b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	might_sleep();
713b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
72e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	if (!key->local->ops->set_key)
733ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg		goto out_unsupported;
7411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
75ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	assert_key_lock(key->local);
76ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg
77dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	sta = get_sta_for_key(key);
78dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg
79e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	/*
80e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	 * If this is a per-STA GTK, check if it
81e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	 * is supported; if not, return.
82e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	 */
83e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	if (sta && !(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE) &&
84e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	    !(key->local->hw.flags & IEEE80211_HW_SUPPORTS_PER_STA_GTK))
85e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg		goto out_unsupported;
86e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg
87dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	sdata = key->sdata;
8818890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
8918890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa		/*
9018890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa		 * The driver doesn't know anything about VLAN interfaces.
9118890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa		 * Hence, don't send GTKs for VLAN interfaces to the driver.
9218890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa		 */
9318890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa		if (!(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE))
9418890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa			goto out_unsupported;
95dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg		sdata = container_of(sdata->bss,
96dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg				     struct ieee80211_sub_if_data,
97dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg				     u.ap);
9818890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa	}
9911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
10012375ef933fa8271396ed0c1e318cb1bd2e2689dJohannes Berg	ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf);
10111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
102e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	if (!ret) {
10311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
104e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg		return 0;
105e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	}
10611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
107e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	if (ret != -ENOSPC && ret != -EOPNOTSUPP)
1080fb9a9ec27718fbf7fa3153bc94becefb716ceebJoe Perches		wiphy_err(key->local->hw.wiphy,
1090fb9a9ec27718fbf7fa3153bc94becefb716ceebJoe Perches			  "failed to set key (%d, %pM) to hardware (%d)\n",
1100fb9a9ec27718fbf7fa3153bc94becefb716ceebJoe Perches			  key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
1113ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg
112e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg out_unsupported:
113e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	switch (key->conf.cipher) {
114e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	case WLAN_CIPHER_SUITE_WEP40:
115e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	case WLAN_CIPHER_SUITE_WEP104:
116e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	case WLAN_CIPHER_SUITE_TKIP:
117e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	case WLAN_CIPHER_SUITE_CCMP:
118e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	case WLAN_CIPHER_SUITE_AES_CMAC:
119e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg		/* all of these we can do in software */
120e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg		return 0;
121e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	default:
122e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg		return -EINVAL;
1233ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg	}
12411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg}
12511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
12611a843b7e16062389c53ba393c7913956e034eb2Johannes Bergstatic void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
12711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg{
128dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	struct ieee80211_sub_if_data *sdata;
129dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	struct ieee80211_sta *sta;
13011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	int ret;
13111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
1323b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	might_sleep();
1333b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
134db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	if (!key || !key->local->ops->set_key)
13511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		return;
13611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
137ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	assert_key_lock(key->local);
138ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg
139ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
14011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		return;
14111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
142dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	sta = get_sta_for_key(key);
143dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	sdata = key->sdata;
144dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg
145dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
146dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg		sdata = container_of(sdata->bss,
147dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg				     struct ieee80211_sub_if_data,
148dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg				     u.ap);
14911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
15012375ef933fa8271396ed0c1e318cb1bd2e2689dJohannes Berg	ret = drv_set_key(key->local, DISABLE_KEY, sdata,
1512448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg			  sta, &key->conf);
15211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
15311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	if (ret)
1540fb9a9ec27718fbf7fa3153bc94becefb716ceebJoe Perches		wiphy_err(key->local->hw.wiphy,
1550fb9a9ec27718fbf7fa3153bc94becefb716ceebJoe Perches			  "failed to remove key (%d, %pM) from hardware (%d)\n",
1560fb9a9ec27718fbf7fa3153bc94becefb716ceebJoe Perches			  key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
15711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
1583b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
1593b96766f0e643f52ae19e134664df6730c737e87Johannes Berg}
1603b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
161e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Bergvoid ieee80211_key_removed(struct ieee80211_key_conf *key_conf)
162e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg{
163e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	struct ieee80211_key *key;
164e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg
165e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	key = container_of(key_conf, struct ieee80211_key, conf);
166e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg
167e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	might_sleep();
168e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	assert_key_lock(key->local);
169e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg
170e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
171e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg
172e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	/*
173e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	 * Flush TX path to avoid attempts to use this key
174e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	 * after this function returns. Until then, drivers
175e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	 * must be prepared to handle the key.
176e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	 */
177e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	synchronize_rcu();
178e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg}
179e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes BergEXPORT_SYMBOL_GPL(ieee80211_key_removed);
180e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg
1813b96766f0e643f52ae19e134664df6730c737e87Johannes Bergstatic void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
182f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg					int idx, bool uni, bool multi)
1833b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{
1843b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	struct ieee80211_key *key = NULL;
1853b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
186ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	assert_key_lock(sdata->local);
187ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg
1883b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	if (idx >= 0 && idx < NUM_DEFAULT_KEYS)
1893b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		key = sdata->keys[idx];
1903b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
191f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg	if (uni)
192f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg		rcu_assign_pointer(sdata->default_unicast_key, key);
193f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg	if (multi)
194f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg		rcu_assign_pointer(sdata->default_multicast_key, key);
1953b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
196f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg	ieee80211_debugfs_key_update_default(sdata);
1973b96766f0e643f52ae19e134664df6730c737e87Johannes Berg}
1983b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
199f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Bergvoid ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx,
200f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg			       bool uni, bool multi)
2013b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{
202ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_lock(&sdata->local->key_mtx);
203f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg	__ieee80211_set_default_key(sdata, idx, uni, multi);
204ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_unlock(&sdata->local->key_mtx);
2053b96766f0e643f52ae19e134664df6730c737e87Johannes Berg}
2063b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2073cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinenstatic void
2083cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen__ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx)
2093cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen{
2103cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	struct ieee80211_key *key = NULL;
2113cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen
212ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	assert_key_lock(sdata->local);
213ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg
2143cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	if (idx >= NUM_DEFAULT_KEYS &&
2153cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	    idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
2163cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		key = sdata->keys[idx];
2173cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen
2183cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	rcu_assign_pointer(sdata->default_mgmt_key, key);
2193cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen
220f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg	ieee80211_debugfs_key_update_default(sdata);
2213cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen}
2223cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen
2233cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinenvoid ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
2243cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen				    int idx)
2253cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen{
226ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_lock(&sdata->local->key_mtx);
2273cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	__ieee80211_set_default_mgmt_key(sdata, idx);
228ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_unlock(&sdata->local->key_mtx);
2293cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen}
2303cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen
2313b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2323b96766f0e643f52ae19e134664df6730c737e87Johannes Bergstatic void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
2333b96766f0e643f52ae19e134664df6730c737e87Johannes Berg				    struct sta_info *sta,
234e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg				    bool pairwise,
2353b96766f0e643f52ae19e134664df6730c737e87Johannes Berg				    struct ieee80211_key *old,
2363b96766f0e643f52ae19e134664df6730c737e87Johannes Berg				    struct ieee80211_key *new)
2373b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{
238f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg	int idx;
239f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg	bool defunikey, defmultikey, defmgmtkey;
2403b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2413b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	if (new)
2423b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		list_add(&new->list, &sdata->key_list);
2433b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
244e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	if (sta && pairwise) {
245e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg		rcu_assign_pointer(sta->ptk, new);
246e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	} else if (sta) {
247e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg		if (old)
248e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg			idx = old->conf.keyidx;
249e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg		else
250e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg			idx = new->conf.keyidx;
251e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg		rcu_assign_pointer(sta->gtk[idx], new);
2523b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	} else {
2533b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx);
2543b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2553b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		if (old)
2563b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			idx = old->conf.keyidx;
2573b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		else
2583b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			idx = new->conf.keyidx;
2593b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
260f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg		defunikey = old && sdata->default_unicast_key == old;
261f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg		defmultikey = old && sdata->default_multicast_key == old;
2623cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		defmgmtkey = old && sdata->default_mgmt_key == old;
2633b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
264f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg		if (defunikey && !new)
265f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg			__ieee80211_set_default_key(sdata, -1, true, false);
266f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg		if (defmultikey && !new)
267f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg			__ieee80211_set_default_key(sdata, -1, false, true);
2683cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		if (defmgmtkey && !new)
2693cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen			__ieee80211_set_default_mgmt_key(sdata, -1);
2703b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2713b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		rcu_assign_pointer(sdata->keys[idx], new);
272f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg		if (defunikey && new)
273f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg			__ieee80211_set_default_key(sdata, new->conf.keyidx,
274f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg						    true, false);
275f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg		if (defmultikey && new)
276f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg			__ieee80211_set_default_key(sdata, new->conf.keyidx,
277f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg						    false, true);
2783cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		if (defmgmtkey && new)
2793cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen			__ieee80211_set_default_mgmt_key(sdata,
2803cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen							 new->conf.keyidx);
2813b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	}
2823b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
283b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg	if (old)
284b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg		list_del(&old->list);
28511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg}
28611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
28797359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Bergstruct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
288faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen					  const u8 *key_data,
289faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen					  size_t seq_len, const u8 *seq)
2901f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg{
2911f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg	struct ieee80211_key *key;
2921ac62ba7c985109868a18d959986425148481f47Ben Hutchings	int i, j, err;
2931f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg
2943cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS);
29511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
29611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL);
2971f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg	if (!key)
2981ac62ba7c985109868a18d959986425148481f47Ben Hutchings		return ERR_PTR(-ENOMEM);
29911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
30011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	/*
30111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	 * Default to software encryption; we'll later upload the
30211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	 * key to the hardware if possible.
30311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	 */
30411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	key->conf.flags = 0;
30511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	key->flags = 0;
30611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
30797359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg	key->conf.cipher = cipher;
30811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	key->conf.keyidx = idx;
30911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	key->conf.keylen = key_len;
31097359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg	switch (cipher) {
31197359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg	case WLAN_CIPHER_SUITE_WEP40:
31297359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg	case WLAN_CIPHER_SUITE_WEP104:
31376708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		key->conf.iv_len = WEP_IV_LEN;
31476708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		key->conf.icv_len = WEP_ICV_LEN;
31576708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		break;
31697359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg	case WLAN_CIPHER_SUITE_TKIP:
31776708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		key->conf.iv_len = TKIP_IV_LEN;
31876708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		key->conf.icv_len = TKIP_ICV_LEN;
3199f26a952210e44691f784b77bf1f83a500d63f58Jouni Malinen		if (seq) {
320faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen			for (i = 0; i < NUM_RX_DATA_QUEUES; i++) {
321faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen				key->u.tkip.rx[i].iv32 =
322faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen					get_unaligned_le32(&seq[2]);
323faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen				key->u.tkip.rx[i].iv16 =
324faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen					get_unaligned_le16(seq);
325faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen			}
326faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen		}
32776708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		break;
32897359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg	case WLAN_CIPHER_SUITE_CCMP:
32976708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		key->conf.iv_len = CCMP_HDR_LEN;
33076708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		key->conf.icv_len = CCMP_MIC_LEN;
3319f26a952210e44691f784b77bf1f83a500d63f58Jouni Malinen		if (seq) {
3329190252c952a33efa1ceff4ef35188f8a27b81cbJouni Malinen			for (i = 0; i < NUM_RX_DATA_QUEUES + 1; i++)
333faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen				for (j = 0; j < CCMP_PN_LEN; j++)
334faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen					key->u.ccmp.rx_pn[i][j] =
335faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen						seq[CCMP_PN_LEN - j - 1];
336faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen		}
33711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		/*
33811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		 * Initialize AES key state here as an optimization so that
33911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		 * it does not need to be initialized for every packet.
34011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		 */
34111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data);
3421ac62ba7c985109868a18d959986425148481f47Ben Hutchings		if (IS_ERR(key->u.ccmp.tfm)) {
3431ac62ba7c985109868a18d959986425148481f47Ben Hutchings			err = PTR_ERR(key->u.ccmp.tfm);
3443b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			kfree(key);
3451ac62ba7c985109868a18d959986425148481f47Ben Hutchings			key = ERR_PTR(err);
34611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		}
34760ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg		break;
34860ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg	case WLAN_CIPHER_SUITE_AES_CMAC:
34960ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg		key->conf.iv_len = 0;
35060ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg		key->conf.icv_len = sizeof(struct ieee80211_mmie);
35160ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg		if (seq)
35260ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg			for (j = 0; j < 6; j++)
35360ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg				key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1];
3543cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		/*
3553cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		 * Initialize AES key state here as an optimization so that
3563cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		 * it does not need to be initialized for every packet.
3573cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		 */
3583cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		key->u.aes_cmac.tfm =
3593cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen			ieee80211_aes_cmac_key_setup(key_data);
3601ac62ba7c985109868a18d959986425148481f47Ben Hutchings		if (IS_ERR(key->u.aes_cmac.tfm)) {
3611ac62ba7c985109868a18d959986425148481f47Ben Hutchings			err = PTR_ERR(key->u.aes_cmac.tfm);
3623cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen			kfree(key);
3631ac62ba7c985109868a18d959986425148481f47Ben Hutchings			key = ERR_PTR(err);
3643cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		}
36560ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg		break;
3663cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	}
36760ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg	memcpy(key->conf.key, key_data, key_len);
36860ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg	INIT_LIST_HEAD(&key->list);
3693cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen
370db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	return key;
371db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg}
37211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
373ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Bergstatic void __ieee80211_key_destroy(struct ieee80211_key *key)
374ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg{
375ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	if (!key)
376ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg		return;
377ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg
37832162a4dab0e6a4ca7f886a01173b5f9b80843beJouni Malinen	if (key->local)
37932162a4dab0e6a4ca7f886a01173b5f9b80843beJouni Malinen		ieee80211_key_disable_hw_accel(key);
380ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg
38197359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg	if (key->conf.cipher == WLAN_CIPHER_SUITE_CCMP)
382ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg		ieee80211_aes_key_free(key->u.ccmp.tfm);
38397359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg	if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC)
384ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg		ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
38532162a4dab0e6a4ca7f886a01173b5f9b80843beJouni Malinen	if (key->local)
38632162a4dab0e6a4ca7f886a01173b5f9b80843beJouni Malinen		ieee80211_debugfs_key_remove(key);
387ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg
388ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	kfree(key);
389ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg}
390ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg
3913ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Bergint ieee80211_key_link(struct ieee80211_key *key,
3923ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg		       struct ieee80211_sub_if_data *sdata,
3933ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg		       struct sta_info *sta)
394db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg{
395db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	struct ieee80211_key *old_key;
3963ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg	int idx, ret;
397e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	bool pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE;
398db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg
399db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	BUG_ON(!sdata);
400db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	BUG_ON(!key);
401db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg
402db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	idx = key->conf.keyidx;
403db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	key->local = sdata->local;
404db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	key->sdata = sdata;
405db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	key->sta = sta;
406db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg
40711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	if (sta) {
40811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		/*
40911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		 * some hardware cannot handle TKIP with QoS, so
41011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		 * we indicate whether QoS could be in use.
41111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		 */
41207346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg		if (test_sta_flags(sta, WLAN_STA_WME))
41311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg			key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA;
41411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	} else {
41505c914fe330fa8e1cc67870dc0d3809dfd96c107Johannes Berg		if (sdata->vif.type == NL80211_IFTYPE_STATION) {
41611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg			struct sta_info *ap;
41711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
4183b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			/*
419b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg			 * We're getting a sta pointer in, so must be under
420b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg			 * appropriate locking for sta_info_get().
4213b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			 */
422d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg
42311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg			/* same here, the AP could be using QoS */
424abe60632f311d515b082b450504ee24006023951Johannes Berg			ap = sta_info_get(key->sdata, key->sdata->u.mgd.bssid);
42511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg			if (ap) {
42607346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg				if (test_sta_flags(ap, WLAN_STA_WME))
42711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg					key->conf.flags |=
42811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg						IEEE80211_KEY_FLAG_WMM_STA;
42911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg			}
43011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		}
43111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	}
43211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
433ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_lock(&sdata->local->key_mtx);
4343b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
435e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	if (sta && pairwise)
436e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg		old_key = sta->ptk;
437e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	else if (sta)
438e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg		old_key = sta->gtk[idx];
439d4e46a3d9869563c6210b01bb651c40cbe65da80Johannes Berg	else
440db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg		old_key = sdata->keys[idx];
441db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg
442e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	__ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
443ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	__ieee80211_key_destroy(old_key);
444d4e46a3d9869563c6210b01bb651c40cbe65da80Johannes Berg
445ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	ieee80211_debugfs_key_add(key);
446db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg
4473ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg	ret = ieee80211_key_enable_hw_accel(key);
448523d2f6982136d332c9b7dd00e9e16da1091f060Johannes Berg
449ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_unlock(&sdata->local->key_mtx);
4503ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg
4513ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg	return ret;
4521f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg}
4531f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg
4543a245766901a9dfdc3f53457a7954b369b50f281Johannes Bergstatic void __ieee80211_key_free(struct ieee80211_key *key)
4551f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg{
4563b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	/*
4573b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	 * Replace key with nothingness if it was ever used.
4583b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	 */
4593a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg	if (key->sdata)
4603b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		__ieee80211_key_replace(key->sdata, key->sta,
461e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg				key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
462e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg				key, NULL);
463ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	__ieee80211_key_destroy(key);
4643b96766f0e643f52ae19e134664df6730c737e87Johannes Berg}
465d4e46a3d9869563c6210b01bb651c40cbe65da80Johannes Berg
46632162a4dab0e6a4ca7f886a01173b5f9b80843beJouni Malinenvoid ieee80211_key_free(struct ieee80211_local *local,
46732162a4dab0e6a4ca7f886a01173b5f9b80843beJouni Malinen			struct ieee80211_key *key)
4683b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{
4693a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg	if (!key)
4703b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		return;
4713b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
472ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_lock(&local->key_mtx);
4733a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg	__ieee80211_key_free(key);
474ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_unlock(&local->key_mtx);
4753a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg}
4763a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg
477ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Bergvoid ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
4783a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg{
4793a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg	struct ieee80211_key *key;
48011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
4813a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg	ASSERT_RTNL();
48211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
4839607e6b66a0d25ca63b70d54a4283fa13d8f7c9dJohannes Berg	if (WARN_ON(!ieee80211_sdata_running(sdata)))
4843a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg		return;
48511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
486ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_lock(&sdata->local->key_mtx);
48711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
488ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	list_for_each_entry(key, &sdata->key_list, list)
489ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg		ieee80211_key_enable_hw_accel(key);
4903b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
491ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_unlock(&sdata->local->key_mtx);
49211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg}
49311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
494ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Bergvoid ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)
49511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg{
49611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	struct ieee80211_key *key;
49711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
498ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	ASSERT_RTNL();
499db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg
500ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_lock(&sdata->local->key_mtx);
50111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
502ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	list_for_each_entry(key, &sdata->key_list, list)
503ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg		ieee80211_key_disable_hw_accel(key);
50411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
505ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_unlock(&sdata->local->key_mtx);
5063b96766f0e643f52ae19e134664df6730c737e87Johannes Berg}
50711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
5083b96766f0e643f52ae19e134664df6730c737e87Johannes Bergvoid ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
5093b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{
5103b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	struct ieee80211_key *key, *tmp;
511db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg
512ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_lock(&sdata->local->key_mtx);
5133b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
5143cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	ieee80211_debugfs_key_remove_mgmt_default(sdata);
5153b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
5163b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
5173a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg		__ieee80211_key_free(key);
5183b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
519f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg	ieee80211_debugfs_key_update_default(sdata);
520f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg
521ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_unlock(&sdata->local->key_mtx);
52211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg}
523