Blame view

net/mac80211/key.c 30.1 KB
1f5a7e47a   Johannes Berg   [MAC80211]: split...
1
2
3
4
  /*
   * Copyright 2002-2005, Instant802 Networks, Inc.
   * Copyright 2005-2006, Devicescape Software, Inc.
   * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
3b96766f0   Johannes Berg   mac80211: fix key...
5
   * Copyright 2007-2008	Johannes Berg <johannes@sipsolutions.net>
d98ad83ee   Johannes Berg   mac80211: add Int...
6
   * Copyright 2013-2014  Intel Mobile Communications GmbH
1f5a7e47a   Johannes Berg   [MAC80211]: split...
7
8
9
10
11
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   */
11a843b7e   Johannes Berg   [MAC80211]: rewor...
12
13
14
  #include <linux/if_ether.h>
  #include <linux/etherdevice.h>
  #include <linux/list.h>
d4e46a3d9   Johannes Berg   [MAC80211]: fix r...
15
  #include <linux/rcupdate.h>
db4d1169d   Johannes Berg   mac80211: split i...
16
  #include <linux/rtnetlink.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
17
  #include <linux/slab.h>
bc3b2d7fb   Paul Gortmaker   net: Add export.h...
18
  #include <linux/export.h>
1f5a7e47a   Johannes Berg   [MAC80211]: split...
19
  #include <net/mac80211.h>
d26ad3771   Johannes Berg   mac80211: clean u...
20
  #include <asm/unaligned.h>
1f5a7e47a   Johannes Berg   [MAC80211]: split...
21
  #include "ieee80211_i.h"
244879813   Johannes Berg   mac80211: add dri...
22
  #include "driver-ops.h"
1f5a7e47a   Johannes Berg   [MAC80211]: split...
23
24
  #include "debugfs_key.h"
  #include "aes_ccm.h"
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
25
  #include "aes_cmac.h"
8ade538bf   Jouni Malinen   mac80111: Add BIP...
26
  #include "aes_gmac.h"
00b9cfa3f   Jouni Malinen   mac80111: Add GCM...
27
  #include "aes_gcm.h"
1f5a7e47a   Johannes Berg   [MAC80211]: split...
28

11a843b7e   Johannes Berg   [MAC80211]: rewor...
29

dbbea6713   Johannes Berg   mac80211: add doc...
30
31
  /**
   * DOC: Key handling basics
11a843b7e   Johannes Berg   [MAC80211]: rewor...
32
33
34
35
36
   *
   * Key handling in mac80211 is done based on per-interface (sub_if_data)
   * keys and per-station keys. Since each station belongs to an interface,
   * each station key also belongs to that interface.
   *
b5c34f662   Johannes Berg   mac80211: fix som...
37
38
39
40
41
42
43
   * Hardware acceleration is done on a best-effort basis for algorithms
   * that are implemented in software,  for each key the hardware is asked
   * to enable that key for offloading but if it cannot do that the key is
   * simply kept for software encryption (unless it is for an algorithm
   * that isn't implemented in software).
   * There is currently no way of knowing whether a key is handled in SW
   * or HW except by looking into debugfs.
11a843b7e   Johannes Berg   [MAC80211]: rewor...
44
   *
b5c34f662   Johannes Berg   mac80211: fix som...
45
46
47
48
49
50
   * All key management is internally protected by a mutex. Within all
   * other parts of mac80211, key references are, just as STA structure
   * references, protected by RCU. Note, however, that some things are
   * unprotected, namely the key->sta dereferences within the hardware
   * acceleration functions. This means that sta_info_destroy() must
   * remove the key which waits for an RCU grace period.
11a843b7e   Johannes Berg   [MAC80211]: rewor...
51
52
53
   */
  
  static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
11a843b7e   Johannes Berg   [MAC80211]: rewor...
54

ad0e2b5a0   Johannes Berg   mac80211: simplif...
55
  static void assert_key_lock(struct ieee80211_local *local)
3b96766f0   Johannes Berg   mac80211: fix key...
56
  {
46a5ebaf0   Johannes Berg   cfg80211/mac80211...
57
  	lockdep_assert_held(&local->key_mtx);
3b96766f0   Johannes Berg   mac80211: fix key...
58
  }
3bff18651   Yogesh Ashok Powar   mac80211: Skip ta...
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
  static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata)
  {
  	/*
  	 * When this count is zero, SKB resizing for allocating tailroom
  	 * for IV or MMIC is skipped. But, this check has created two race
  	 * cases in xmit path while transiting from zero count to one:
  	 *
  	 * 1. SKB resize was skipped because no key was added but just before
  	 * the xmit key is added and SW encryption kicks off.
  	 *
  	 * 2. SKB resize was skipped because all the keys were hw planted but
  	 * just before xmit one of the key is deleted and SW encryption kicks
  	 * off.
  	 *
  	 * In both the above case SW encryption will find not enough space for
  	 * tailroom and exits with WARN_ON. (See WARN_ONs at wpa.c)
  	 *
  	 * Solution has been explained at
  	 * http://mid.gmane.org/1308590980.4322.19.camel@jlt3.sipsolutions.net
  	 */
  
  	if (!sdata->crypto_tx_tailroom_needed_cnt++) {
  		/*
  		 * Flush all XMIT packets currently using HW encryption or no
  		 * encryption at all if the count transition is from 0 -> 1.
  		 */
  		synchronize_net();
  	}
  }
3ffc2a905   Johannes Berg   mac80211: allow v...
88
  static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
11a843b7e   Johannes Berg   [MAC80211]: rewor...
89
  {
dc822b5db   Johannes Berg   mac80211: clean u...
90
  	struct ieee80211_sub_if_data *sdata;
89c91caec   Johannes Berg   mac80211: dont pr...
91
  	struct sta_info *sta;
fa7e1fbcb   Johannes Berg   mac80211: allow d...
92
  	int ret = -EOPNOTSUPP;
11a843b7e   Johannes Berg   [MAC80211]: rewor...
93

3b96766f0   Johannes Berg   mac80211: fix key...
94
  	might_sleep();
4619194a4   Johannes Berg   mac80211: don't r...
95
96
97
98
99
100
101
102
103
  	if (key->flags & KEY_FLAG_TAINTED) {
  		/* If we get here, it's during resume and the key is
  		 * tainted so shouldn't be used/programmed any more.
  		 * However, its flags may still indicate that it was
  		 * programmed into the device (since we're in resume)
  		 * so clear that flag now to avoid trying to remove
  		 * it again later.
  		 */
  		key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
27b3eb9c0   Johannes Berg   mac80211: add API...
104
  		return -EINVAL;
4619194a4   Johannes Berg   mac80211: don't r...
105
  	}
27b3eb9c0   Johannes Berg   mac80211: add API...
106

e31b82136   Johannes Berg   cfg80211/mac80211...
107
  	if (!key->local->ops->set_key)
3ffc2a905   Johannes Berg   mac80211: allow v...
108
  		goto out_unsupported;
11a843b7e   Johannes Berg   [MAC80211]: rewor...
109

ad0e2b5a0   Johannes Berg   mac80211: simplif...
110
  	assert_key_lock(key->local);
89c91caec   Johannes Berg   mac80211: dont pr...
111
  	sta = key->sta;
dc822b5db   Johannes Berg   mac80211: clean u...
112

e31b82136   Johannes Berg   cfg80211/mac80211...
113
114
115
116
117
118
119
  	/*
  	 * If this is a per-STA GTK, check if it
  	 * is supported; if not, return.
  	 */
  	if (sta && !(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE) &&
  	    !(key->local->hw.flags & IEEE80211_HW_SUPPORTS_PER_STA_GTK))
  		goto out_unsupported;
89c91caec   Johannes Berg   mac80211: dont pr...
120
121
  	if (sta && !sta->uploaded)
  		goto out_unsupported;
dc822b5db   Johannes Berg   mac80211: clean u...
122
  	sdata = key->sdata;
18890d4b8   Helmut Schaa   mac80211: Disable...
123
124
125
126
127
128
129
  	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
  		/*
  		 * The driver doesn't know anything about VLAN interfaces.
  		 * Hence, don't send GTKs for VLAN interfaces to the driver.
  		 */
  		if (!(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE))
  			goto out_unsupported;
18890d4b8   Helmut Schaa   mac80211: Disable...
130
  	}
11a843b7e   Johannes Berg   [MAC80211]: rewor...
131

89c91caec   Johannes Berg   mac80211: dont pr...
132
133
  	ret = drv_set_key(key->local, SET_KEY, sdata,
  			  sta ? &sta->sta : NULL, &key->conf);
11a843b7e   Johannes Berg   [MAC80211]: rewor...
134

e31b82136   Johannes Berg   cfg80211/mac80211...
135
  	if (!ret) {
11a843b7e   Johannes Berg   [MAC80211]: rewor...
136
  		key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
3bff18651   Yogesh Ashok Powar   mac80211: Skip ta...
137

1e359a5de   Johannes Berg   Revert "mac80211:...
138
  		if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
db12847ca   Ido Yariv   mac80211: Re-fix ...
139
  		      (key->conf.flags & IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
3bff18651   Yogesh Ashok Powar   mac80211: Skip ta...
140
  			sdata->crypto_tx_tailroom_needed_cnt--;
077a91548   Arik Nemtsov   mac80211: support...
141
142
  		WARN_ON((key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE) &&
  			(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV));
e31b82136   Johannes Berg   cfg80211/mac80211...
143
144
  		return 0;
  	}
11a843b7e   Johannes Berg   [MAC80211]: rewor...
145

fa7e1fbcb   Johannes Berg   mac80211: allow d...
146
  	if (ret != -ENOSPC && ret != -EOPNOTSUPP && ret != 1)
bdcbd8e0e   Johannes Berg   mac80211: clean u...
147
  		sdata_err(sdata,
0fb9a9ec2   Joe Perches   net/mac80211: Use...
148
149
  			  "failed to set key (%d, %pM) to hardware (%d)
  ",
89c91caec   Johannes Berg   mac80211: dont pr...
150
151
  			  key->conf.keyidx,
  			  sta ? sta->sta.addr : bcast_addr, ret);
3ffc2a905   Johannes Berg   mac80211: allow v...
152

e31b82136   Johannes Berg   cfg80211/mac80211...
153
154
155
156
157
158
   out_unsupported:
  	switch (key->conf.cipher) {
  	case WLAN_CIPHER_SUITE_WEP40:
  	case WLAN_CIPHER_SUITE_WEP104:
  	case WLAN_CIPHER_SUITE_TKIP:
  	case WLAN_CIPHER_SUITE_CCMP:
2b2ba0db1   Jouni Malinen   mac80111: Add CCM...
159
  	case WLAN_CIPHER_SUITE_CCMP_256:
e31b82136   Johannes Berg   cfg80211/mac80211...
160
  	case WLAN_CIPHER_SUITE_AES_CMAC:
56c52da2d   Jouni Malinen   mac80111: Add BIP...
161
  	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
8ade538bf   Jouni Malinen   mac80111: Add BIP...
162
163
  	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
  	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
00b9cfa3f   Jouni Malinen   mac80111: Add GCM...
164
165
  	case WLAN_CIPHER_SUITE_GCMP:
  	case WLAN_CIPHER_SUITE_GCMP_256:
fa7e1fbcb   Johannes Berg   mac80211: allow d...
166
167
168
169
170
  		/* all of these we can do in software - if driver can */
  		if (ret == 1)
  			return 0;
  		if (key->local->hw.flags & IEEE80211_HW_SW_CRYPTO_CONTROL)
  			return -EINVAL;
e31b82136   Johannes Berg   cfg80211/mac80211...
171
172
173
  		return 0;
  	default:
  		return -EINVAL;
3ffc2a905   Johannes Berg   mac80211: allow v...
174
  	}
11a843b7e   Johannes Berg   [MAC80211]: rewor...
175
176
177
178
  }
  
  static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
  {
dc822b5db   Johannes Berg   mac80211: clean u...
179
  	struct ieee80211_sub_if_data *sdata;
89c91caec   Johannes Berg   mac80211: dont pr...
180
  	struct sta_info *sta;
11a843b7e   Johannes Berg   [MAC80211]: rewor...
181
  	int ret;
3b96766f0   Johannes Berg   mac80211: fix key...
182
  	might_sleep();
db4d1169d   Johannes Berg   mac80211: split i...
183
  	if (!key || !key->local->ops->set_key)
11a843b7e   Johannes Berg   [MAC80211]: rewor...
184
  		return;
ad0e2b5a0   Johannes Berg   mac80211: simplif...
185
186
187
  	assert_key_lock(key->local);
  
  	if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
11a843b7e   Johannes Berg   [MAC80211]: rewor...
188
  		return;
89c91caec   Johannes Berg   mac80211: dont pr...
189
  	sta = key->sta;
dc822b5db   Johannes Berg   mac80211: clean u...
190
  	sdata = key->sdata;
1e359a5de   Johannes Berg   Revert "mac80211:...
191
  	if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
db12847ca   Ido Yariv   mac80211: Re-fix ...
192
  	      (key->conf.flags & IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
3bff18651   Yogesh Ashok Powar   mac80211: Skip ta...
193
  		increment_tailroom_need_count(sdata);
12375ef93   Johannes Berg   mac80211: trace i...
194
  	ret = drv_set_key(key->local, DISABLE_KEY, sdata,
89c91caec   Johannes Berg   mac80211: dont pr...
195
  			  sta ? &sta->sta : NULL, &key->conf);
11a843b7e   Johannes Berg   [MAC80211]: rewor...
196
197
  
  	if (ret)
bdcbd8e0e   Johannes Berg   mac80211: clean u...
198
  		sdata_err(sdata,
0fb9a9ec2   Joe Perches   net/mac80211: Use...
199
200
  			  "failed to remove key (%d, %pM) from hardware (%d)
  ",
89c91caec   Johannes Berg   mac80211: dont pr...
201
202
  			  key->conf.keyidx,
  			  sta ? sta->sta.addr : bcast_addr, ret);
11a843b7e   Johannes Berg   [MAC80211]: rewor...
203

3b96766f0   Johannes Berg   mac80211: fix key...
204
  	key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
3b96766f0   Johannes Berg   mac80211: fix key...
205
206
207
  }
  
  static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
f7e0104c1   Johannes Berg   mac80211: support...
208
  					int idx, bool uni, bool multi)
3b96766f0   Johannes Berg   mac80211: fix key...
209
210
  {
  	struct ieee80211_key *key = NULL;
ad0e2b5a0   Johannes Berg   mac80211: simplif...
211
  	assert_key_lock(sdata->local);
3b96766f0   Johannes Berg   mac80211: fix key...
212
  	if (idx >= 0 && idx < NUM_DEFAULT_KEYS)
40b275b69   Johannes Berg   mac80211: sparse ...
213
  		key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
3b96766f0   Johannes Berg   mac80211: fix key...
214

de5fad815   Yoni Divinsky   mac80211: add op ...
215
  	if (uni) {
f7e0104c1   Johannes Berg   mac80211: support...
216
  		rcu_assign_pointer(sdata->default_unicast_key, key);
de5fad815   Yoni Divinsky   mac80211: add op ...
217
218
  		drv_set_default_unicast_key(sdata->local, sdata, idx);
  	}
f7e0104c1   Johannes Berg   mac80211: support...
219
220
  	if (multi)
  		rcu_assign_pointer(sdata->default_multicast_key, key);
3b96766f0   Johannes Berg   mac80211: fix key...
221

f7e0104c1   Johannes Berg   mac80211: support...
222
  	ieee80211_debugfs_key_update_default(sdata);
3b96766f0   Johannes Berg   mac80211: fix key...
223
  }
f7e0104c1   Johannes Berg   mac80211: support...
224
225
  void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx,
  			       bool uni, bool multi)
3b96766f0   Johannes Berg   mac80211: fix key...
226
  {
ad0e2b5a0   Johannes Berg   mac80211: simplif...
227
  	mutex_lock(&sdata->local->key_mtx);
f7e0104c1   Johannes Berg   mac80211: support...
228
  	__ieee80211_set_default_key(sdata, idx, uni, multi);
ad0e2b5a0   Johannes Berg   mac80211: simplif...
229
  	mutex_unlock(&sdata->local->key_mtx);
3b96766f0   Johannes Berg   mac80211: fix key...
230
  }
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
231
232
233
234
  static void
  __ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx)
  {
  	struct ieee80211_key *key = NULL;
ad0e2b5a0   Johannes Berg   mac80211: simplif...
235
  	assert_key_lock(sdata->local);
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
236
237
  	if (idx >= NUM_DEFAULT_KEYS &&
  	    idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
40b275b69   Johannes Berg   mac80211: sparse ...
238
  		key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
239
240
  
  	rcu_assign_pointer(sdata->default_mgmt_key, key);
f7e0104c1   Johannes Berg   mac80211: support...
241
  	ieee80211_debugfs_key_update_default(sdata);
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
242
243
244
245
246
  }
  
  void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
  				    int idx)
  {
ad0e2b5a0   Johannes Berg   mac80211: simplif...
247
  	mutex_lock(&sdata->local->key_mtx);
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
248
  	__ieee80211_set_default_mgmt_key(sdata, idx);
ad0e2b5a0   Johannes Berg   mac80211: simplif...
249
  	mutex_unlock(&sdata->local->key_mtx);
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
250
  }
3b96766f0   Johannes Berg   mac80211: fix key...
251

3b8d9c290   Johannes Berg   mac80211: remove ...
252
253
254
255
256
  static void ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
  				  struct sta_info *sta,
  				  bool pairwise,
  				  struct ieee80211_key *old,
  				  struct ieee80211_key *new)
3b96766f0   Johannes Berg   mac80211: fix key...
257
  {
f7e0104c1   Johannes Berg   mac80211: support...
258
259
  	int idx;
  	bool defunikey, defmultikey, defmgmtkey;
3b96766f0   Johannes Berg   mac80211: fix key...
260

5282c3ba4   Johannes Berg   mac80211: verify ...
261
262
263
  	/* caller must provide at least one old/new */
  	if (WARN_ON(!new && !old))
  		return;
3b96766f0   Johannes Berg   mac80211: fix key...
264
  	if (new)
f850e00fc   Johannes Berg   mac80211: let key...
265
  		list_add_tail(&new->list, &sdata->key_list);
3b96766f0   Johannes Berg   mac80211: fix key...
266

2475b1cc0   Max Stepanov   mac80211: add gen...
267
  	WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx);
3b96766f0   Johannes Berg   mac80211: fix key...
268

2475b1cc0   Max Stepanov   mac80211: add gen...
269
270
271
272
  	if (old)
  		idx = old->conf.keyidx;
  	else
  		idx = new->conf.keyidx;
3b96766f0   Johannes Berg   mac80211: fix key...
273

2475b1cc0   Max Stepanov   mac80211: add gen...
274
275
276
277
278
279
280
281
282
  	if (sta) {
  		if (pairwise) {
  			rcu_assign_pointer(sta->ptk[idx], new);
  			sta->ptk_idx = idx;
  		} else {
  			rcu_assign_pointer(sta->gtk[idx], new);
  			sta->gtk_idx = idx;
  		}
  	} else {
40b275b69   Johannes Berg   mac80211: sparse ...
283
284
285
286
287
288
289
290
291
  		defunikey = old &&
  			old == key_mtx_dereference(sdata->local,
  						sdata->default_unicast_key);
  		defmultikey = old &&
  			old == key_mtx_dereference(sdata->local,
  						sdata->default_multicast_key);
  		defmgmtkey = old &&
  			old == key_mtx_dereference(sdata->local,
  						sdata->default_mgmt_key);
3b96766f0   Johannes Berg   mac80211: fix key...
292

f7e0104c1   Johannes Berg   mac80211: support...
293
294
295
296
  		if (defunikey && !new)
  			__ieee80211_set_default_key(sdata, -1, true, false);
  		if (defmultikey && !new)
  			__ieee80211_set_default_key(sdata, -1, false, true);
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
297
298
  		if (defmgmtkey && !new)
  			__ieee80211_set_default_mgmt_key(sdata, -1);
3b96766f0   Johannes Berg   mac80211: fix key...
299
300
  
  		rcu_assign_pointer(sdata->keys[idx], new);
f7e0104c1   Johannes Berg   mac80211: support...
301
302
303
304
305
306
  		if (defunikey && new)
  			__ieee80211_set_default_key(sdata, new->conf.keyidx,
  						    true, false);
  		if (defmultikey && new)
  			__ieee80211_set_default_key(sdata, new->conf.keyidx,
  						    false, true);
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
307
308
309
  		if (defmgmtkey && new)
  			__ieee80211_set_default_mgmt_key(sdata,
  							 new->conf.keyidx);
3b96766f0   Johannes Berg   mac80211: fix key...
310
  	}
b5c34f662   Johannes Berg   mac80211: fix som...
311
312
  	if (old)
  		list_del(&old->list);
11a843b7e   Johannes Berg   [MAC80211]: rewor...
313
  }
2475b1cc0   Max Stepanov   mac80211: add gen...
314
315
316
317
318
  struct ieee80211_key *
  ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
  		    const u8 *key_data,
  		    size_t seq_len, const u8 *seq,
  		    const struct ieee80211_cipher_scheme *cs)
1f5a7e47a   Johannes Berg   [MAC80211]: split...
319
320
  {
  	struct ieee80211_key *key;
1ac62ba7c   Ben Hutchings   mac80211: Don't s...
321
  	int i, j, err;
1f5a7e47a   Johannes Berg   [MAC80211]: split...
322

8c5bb1fad   Johannes Berg   mac80211: remove ...
323
324
  	if (WARN_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS))
  		return ERR_PTR(-EINVAL);
11a843b7e   Johannes Berg   [MAC80211]: rewor...
325
326
  
  	key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL);
1f5a7e47a   Johannes Berg   [MAC80211]: split...
327
  	if (!key)
1ac62ba7c   Ben Hutchings   mac80211: Don't s...
328
  		return ERR_PTR(-ENOMEM);
11a843b7e   Johannes Berg   [MAC80211]: rewor...
329
330
331
332
333
  
  	/*
  	 * Default to software encryption; we'll later upload the
  	 * key to the hardware if possible.
  	 */
11a843b7e   Johannes Berg   [MAC80211]: rewor...
334
335
  	key->conf.flags = 0;
  	key->flags = 0;
97359d123   Johannes Berg   mac80211: use cip...
336
  	key->conf.cipher = cipher;
11a843b7e   Johannes Berg   [MAC80211]: rewor...
337
338
  	key->conf.keyidx = idx;
  	key->conf.keylen = key_len;
97359d123   Johannes Berg   mac80211: use cip...
339
340
341
  	switch (cipher) {
  	case WLAN_CIPHER_SUITE_WEP40:
  	case WLAN_CIPHER_SUITE_WEP104:
4325f6caa   Johannes Berg   wireless: move cr...
342
343
  		key->conf.iv_len = IEEE80211_WEP_IV_LEN;
  		key->conf.icv_len = IEEE80211_WEP_ICV_LEN;
76708dee3   Felix Fietkau   mac80211: free up...
344
  		break;
97359d123   Johannes Berg   mac80211: use cip...
345
  	case WLAN_CIPHER_SUITE_TKIP:
4325f6caa   Johannes Berg   wireless: move cr...
346
347
  		key->conf.iv_len = IEEE80211_TKIP_IV_LEN;
  		key->conf.icv_len = IEEE80211_TKIP_ICV_LEN;
9f26a9522   Jouni Malinen   nl80211: Validate...
348
  		if (seq) {
5a306f588   Johannes Berg   mac80211: introdu...
349
  			for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
faa8fdc85   Jouni Malinen   nl80211: Add RSC ...
350
351
352
353
354
355
  				key->u.tkip.rx[i].iv32 =
  					get_unaligned_le32(&seq[2]);
  				key->u.tkip.rx[i].iv16 =
  					get_unaligned_le16(seq);
  			}
  		}
523b02ea2   Johannes Berg   mac80211: fix TKI...
356
  		spin_lock_init(&key->u.tkip.txlock);
76708dee3   Felix Fietkau   mac80211: free up...
357
  		break;
97359d123   Johannes Berg   mac80211: use cip...
358
  	case WLAN_CIPHER_SUITE_CCMP:
4325f6caa   Johannes Berg   wireless: move cr...
359
360
  		key->conf.iv_len = IEEE80211_CCMP_HDR_LEN;
  		key->conf.icv_len = IEEE80211_CCMP_MIC_LEN;
9f26a9522   Jouni Malinen   nl80211: Validate...
361
  		if (seq) {
5a306f588   Johannes Berg   mac80211: introdu...
362
  			for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++)
4325f6caa   Johannes Berg   wireless: move cr...
363
  				for (j = 0; j < IEEE80211_CCMP_PN_LEN; j++)
faa8fdc85   Jouni Malinen   nl80211: Add RSC ...
364
  					key->u.ccmp.rx_pn[i][j] =
4325f6caa   Johannes Berg   wireless: move cr...
365
  						seq[IEEE80211_CCMP_PN_LEN - j - 1];
faa8fdc85   Jouni Malinen   nl80211: Add RSC ...
366
  		}
11a843b7e   Johannes Berg   [MAC80211]: rewor...
367
368
369
370
  		/*
  		 * Initialize AES key state here as an optimization so that
  		 * it does not need to be initialized for every packet.
  		 */
2b2ba0db1   Jouni Malinen   mac80111: Add CCM...
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
  		key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(
  			key_data, key_len, IEEE80211_CCMP_MIC_LEN);
  		if (IS_ERR(key->u.ccmp.tfm)) {
  			err = PTR_ERR(key->u.ccmp.tfm);
  			kfree(key);
  			return ERR_PTR(err);
  		}
  		break;
  	case WLAN_CIPHER_SUITE_CCMP_256:
  		key->conf.iv_len = IEEE80211_CCMP_256_HDR_LEN;
  		key->conf.icv_len = IEEE80211_CCMP_256_MIC_LEN;
  		for (i = 0; seq && i < IEEE80211_NUM_TIDS + 1; i++)
  			for (j = 0; j < IEEE80211_CCMP_256_PN_LEN; j++)
  				key->u.ccmp.rx_pn[i][j] =
  					seq[IEEE80211_CCMP_256_PN_LEN - j - 1];
  		/* Initialize AES key state here as an optimization so that
  		 * it does not need to be initialized for every packet.
  		 */
  		key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(
  			key_data, key_len, IEEE80211_CCMP_256_MIC_LEN);
1ac62ba7c   Ben Hutchings   mac80211: Don't s...
391
392
  		if (IS_ERR(key->u.ccmp.tfm)) {
  			err = PTR_ERR(key->u.ccmp.tfm);
3b96766f0   Johannes Berg   mac80211: fix key...
393
  			kfree(key);
1f951a7f8   Petr Å tetiar   mac80211: fix NUL...
394
  			return ERR_PTR(err);
11a843b7e   Johannes Berg   [MAC80211]: rewor...
395
  		}
60ae0f200   Johannes Berg   mac80211: move ke...
396
397
  		break;
  	case WLAN_CIPHER_SUITE_AES_CMAC:
56c52da2d   Jouni Malinen   mac80111: Add BIP...
398
  	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
60ae0f200   Johannes Berg   mac80211: move ke...
399
  		key->conf.iv_len = 0;
56c52da2d   Jouni Malinen   mac80111: Add BIP...
400
401
402
403
  		if (cipher == WLAN_CIPHER_SUITE_AES_CMAC)
  			key->conf.icv_len = sizeof(struct ieee80211_mmie);
  		else
  			key->conf.icv_len = sizeof(struct ieee80211_mmie_16);
60ae0f200   Johannes Berg   mac80211: move ke...
404
  		if (seq)
4325f6caa   Johannes Berg   wireless: move cr...
405
  			for (j = 0; j < IEEE80211_CMAC_PN_LEN; j++)
0f9273234   Johannes Berg   mac80211: use CMA...
406
  				key->u.aes_cmac.rx_pn[j] =
4325f6caa   Johannes Berg   wireless: move cr...
407
  					seq[IEEE80211_CMAC_PN_LEN - j - 1];
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
408
409
410
411
412
  		/*
  		 * Initialize AES key state here as an optimization so that
  		 * it does not need to be initialized for every packet.
  		 */
  		key->u.aes_cmac.tfm =
56c52da2d   Jouni Malinen   mac80111: Add BIP...
413
  			ieee80211_aes_cmac_key_setup(key_data, key_len);
1ac62ba7c   Ben Hutchings   mac80211: Don't s...
414
415
  		if (IS_ERR(key->u.aes_cmac.tfm)) {
  			err = PTR_ERR(key->u.aes_cmac.tfm);
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
416
  			kfree(key);
1f951a7f8   Petr Å tetiar   mac80211: fix NUL...
417
  			return ERR_PTR(err);
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
418
  		}
60ae0f200   Johannes Berg   mac80211: move ke...
419
  		break;
8ade538bf   Jouni Malinen   mac80111: Add BIP...
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
  	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
  	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
  		key->conf.iv_len = 0;
  		key->conf.icv_len = sizeof(struct ieee80211_mmie_16);
  		if (seq)
  			for (j = 0; j < IEEE80211_GMAC_PN_LEN; j++)
  				key->u.aes_gmac.rx_pn[j] =
  					seq[IEEE80211_GMAC_PN_LEN - j - 1];
  		/* Initialize AES key state here as an optimization so that
  		 * it does not need to be initialized for every packet.
  		 */
  		key->u.aes_gmac.tfm =
  			ieee80211_aes_gmac_key_setup(key_data, key_len);
  		if (IS_ERR(key->u.aes_gmac.tfm)) {
  			err = PTR_ERR(key->u.aes_gmac.tfm);
  			kfree(key);
  			return ERR_PTR(err);
  		}
  		break;
00b9cfa3f   Jouni Malinen   mac80111: Add GCM...
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
  	case WLAN_CIPHER_SUITE_GCMP:
  	case WLAN_CIPHER_SUITE_GCMP_256:
  		key->conf.iv_len = IEEE80211_GCMP_HDR_LEN;
  		key->conf.icv_len = IEEE80211_GCMP_MIC_LEN;
  		for (i = 0; seq && i < IEEE80211_NUM_TIDS + 1; i++)
  			for (j = 0; j < IEEE80211_GCMP_PN_LEN; j++)
  				key->u.gcmp.rx_pn[i][j] =
  					seq[IEEE80211_GCMP_PN_LEN - j - 1];
  		/* Initialize AES key state here as an optimization so that
  		 * it does not need to be initialized for every packet.
  		 */
  		key->u.gcmp.tfm = ieee80211_aes_gcm_key_setup_encrypt(key_data,
  								      key_len);
  		if (IS_ERR(key->u.gcmp.tfm)) {
  			err = PTR_ERR(key->u.gcmp.tfm);
  			kfree(key);
  			return ERR_PTR(err);
  		}
  		break;
2475b1cc0   Max Stepanov   mac80211: add gen...
458
459
460
461
462
463
464
465
466
467
468
  	default:
  		if (cs) {
  			size_t len = (seq_len > MAX_PN_LEN) ?
  						MAX_PN_LEN : seq_len;
  
  			key->conf.iv_len = cs->hdr_len;
  			key->conf.icv_len = cs->mic_len;
  			for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++)
  				for (j = 0; j < len; j++)
  					key->u.gen.rx_pn[i][j] =
  							seq[len - j - 1];
c7ef38e0c   Cedric Izoard   mac80211: Get IV ...
469
  			key->flags |= KEY_FLAG_CIPHER_SCHEME;
2475b1cc0   Max Stepanov   mac80211: add gen...
470
  		}
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
471
  	}
60ae0f200   Johannes Berg   mac80211: move ke...
472
473
  	memcpy(key->conf.key, key_data, key_len);
  	INIT_LIST_HEAD(&key->list);
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
474

db4d1169d   Johannes Berg   mac80211: split i...
475
476
  	return key;
  }
11a843b7e   Johannes Berg   [MAC80211]: rewor...
477

79cf2dfa3   Johannes Berg   mac80211: clean u...
478
479
  static void ieee80211_key_free_common(struct ieee80211_key *key)
  {
00b9cfa3f   Jouni Malinen   mac80111: Add GCM...
480
481
  	switch (key->conf.cipher) {
  	case WLAN_CIPHER_SUITE_CCMP:
2b2ba0db1   Jouni Malinen   mac80111: Add CCM...
482
  	case WLAN_CIPHER_SUITE_CCMP_256:
79cf2dfa3   Johannes Berg   mac80211: clean u...
483
  		ieee80211_aes_key_free(key->u.ccmp.tfm);
00b9cfa3f   Jouni Malinen   mac80111: Add GCM...
484
485
  		break;
  	case WLAN_CIPHER_SUITE_AES_CMAC:
56c52da2d   Jouni Malinen   mac80111: Add BIP...
486
  	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
79cf2dfa3   Johannes Berg   mac80211: clean u...
487
  		ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
00b9cfa3f   Jouni Malinen   mac80111: Add GCM...
488
  		break;
8ade538bf   Jouni Malinen   mac80111: Add BIP...
489
490
491
492
  	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
  	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
  		ieee80211_aes_gmac_key_free(key->u.aes_gmac.tfm);
  		break;
00b9cfa3f   Jouni Malinen   mac80111: Add GCM...
493
494
495
496
497
  	case WLAN_CIPHER_SUITE_GCMP:
  	case WLAN_CIPHER_SUITE_GCMP_256:
  		ieee80211_aes_gcm_key_free(key->u.gcmp.tfm);
  		break;
  	}
29c3f9c39   Johannes Berg   mac80211: clear k...
498
  	kzfree(key);
79cf2dfa3   Johannes Berg   mac80211: clean u...
499
  }
6d10e46be   Johannes Berg   mac80211: batch k...
500
501
  static void __ieee80211_key_destroy(struct ieee80211_key *key,
  				    bool delay_tailroom)
ad0e2b5a0   Johannes Berg   mac80211: simplif...
502
  {
32162a4da   Jouni Malinen   mac80211: Fix key...
503
504
  	if (key->local)
  		ieee80211_key_disable_hw_accel(key);
ad0e2b5a0   Johannes Berg   mac80211: simplif...
505

3bff18651   Yogesh Ashok Powar   mac80211: Skip ta...
506
  	if (key->local) {
8d1f7ecd2   Johannes Berg   mac80211: defer t...
507
  		struct ieee80211_sub_if_data *sdata = key->sdata;
32162a4da   Jouni Malinen   mac80211: Fix key...
508
  		ieee80211_debugfs_key_remove(key);
8d1f7ecd2   Johannes Berg   mac80211: defer t...
509
510
511
512
513
514
515
516
517
  
  		if (delay_tailroom) {
  			/* see ieee80211_delayed_tailroom_dec */
  			sdata->crypto_tx_tailroom_pending_dec++;
  			schedule_delayed_work(&sdata->dec_tailroom_needed_wk,
  					      HZ/2);
  		} else {
  			sdata->crypto_tx_tailroom_needed_cnt--;
  		}
3bff18651   Yogesh Ashok Powar   mac80211: Skip ta...
518
  	}
ad0e2b5a0   Johannes Berg   mac80211: simplif...
519

79cf2dfa3   Johannes Berg   mac80211: clean u...
520
521
  	ieee80211_key_free_common(key);
  }
6d10e46be   Johannes Berg   mac80211: batch k...
522
523
524
525
526
527
528
529
530
531
532
533
534
535
  static void ieee80211_key_destroy(struct ieee80211_key *key,
  				  bool delay_tailroom)
  {
  	if (!key)
  		return;
  
  	/*
  	 * Synchronize so the TX path can no longer be using
  	 * this key before we free/remove it.
  	 */
  	synchronize_net();
  
  	__ieee80211_key_destroy(key, delay_tailroom);
  }
79cf2dfa3   Johannes Berg   mac80211: clean u...
536
537
538
539
  void ieee80211_key_free_unused(struct ieee80211_key *key)
  {
  	WARN_ON(key->sdata || key->local);
  	ieee80211_key_free_common(key);
ad0e2b5a0   Johannes Berg   mac80211: simplif...
540
  }
3ffc2a905   Johannes Berg   mac80211: allow v...
541
542
543
  int ieee80211_key_link(struct ieee80211_key *key,
  		       struct ieee80211_sub_if_data *sdata,
  		       struct sta_info *sta)
db4d1169d   Johannes Berg   mac80211: split i...
544
  {
27b3eb9c0   Johannes Berg   mac80211: add API...
545
  	struct ieee80211_local *local = sdata->local;
db4d1169d   Johannes Berg   mac80211: split i...
546
  	struct ieee80211_key *old_key;
3ffc2a905   Johannes Berg   mac80211: allow v...
547
  	int idx, ret;
67aa030c0   Mariusz Kozlowski   mac80211: fix pos...
548
  	bool pairwise;
db4d1169d   Johannes Berg   mac80211: split i...
549

67aa030c0   Mariusz Kozlowski   mac80211: fix pos...
550
  	pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE;
db4d1169d   Johannes Berg   mac80211: split i...
551
552
553
554
  	idx = key->conf.keyidx;
  	key->local = sdata->local;
  	key->sdata = sdata;
  	key->sta = sta;
ad0e2b5a0   Johannes Berg   mac80211: simplif...
555
  	mutex_lock(&sdata->local->key_mtx);
3b96766f0   Johannes Berg   mac80211: fix key...
556

e31b82136   Johannes Berg   cfg80211/mac80211...
557
  	if (sta && pairwise)
2475b1cc0   Max Stepanov   mac80211: add gen...
558
  		old_key = key_mtx_dereference(sdata->local, sta->ptk[idx]);
e31b82136   Johannes Berg   cfg80211/mac80211...
559
  	else if (sta)
40b275b69   Johannes Berg   mac80211: sparse ...
560
  		old_key = key_mtx_dereference(sdata->local, sta->gtk[idx]);
d4e46a3d9   Johannes Berg   [MAC80211]: fix r...
561
  	else
40b275b69   Johannes Berg   mac80211: sparse ...
562
  		old_key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
db4d1169d   Johannes Berg   mac80211: split i...
563

3bff18651   Yogesh Ashok Powar   mac80211: Skip ta...
564
  	increment_tailroom_need_count(sdata);
3b8d9c290   Johannes Berg   mac80211: remove ...
565
566
  	ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
  	ieee80211_key_destroy(old_key, true);
d4e46a3d9   Johannes Berg   [MAC80211]: fix r...
567

ad0e2b5a0   Johannes Berg   mac80211: simplif...
568
  	ieee80211_debugfs_key_add(key);
db4d1169d   Johannes Berg   mac80211: split i...
569

27b3eb9c0   Johannes Berg   mac80211: add API...
570
571
572
573
574
575
576
  	if (!local->wowlan) {
  		ret = ieee80211_key_enable_hw_accel(key);
  		if (ret)
  			ieee80211_key_free(key, true);
  	} else {
  		ret = 0;
  	}
79cf2dfa3   Johannes Berg   mac80211: clean u...
577

ad0e2b5a0   Johannes Berg   mac80211: simplif...
578
  	mutex_unlock(&sdata->local->key_mtx);
3ffc2a905   Johannes Berg   mac80211: allow v...
579
580
  
  	return ret;
1f5a7e47a   Johannes Berg   [MAC80211]: split...
581
  }
3b8d9c290   Johannes Berg   mac80211: remove ...
582
  void ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom)
1f5a7e47a   Johannes Berg   [MAC80211]: split...
583
  {
5c0c36412   Johannes Berg   mac80211: make ke...
584
585
  	if (!key)
  		return;
3b96766f0   Johannes Berg   mac80211: fix key...
586
587
588
  	/*
  	 * Replace key with nothingness if it was ever used.
  	 */
3a2457669   Johannes Berg   mac80211: fix key...
589
  	if (key->sdata)
3b8d9c290   Johannes Berg   mac80211: remove ...
590
  		ieee80211_key_replace(key->sdata, key->sta,
e31b82136   Johannes Berg   cfg80211/mac80211...
591
592
  				key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
  				key, NULL);
3b8d9c290   Johannes Berg   mac80211: remove ...
593
  	ieee80211_key_destroy(key, delay_tailroom);
3b96766f0   Johannes Berg   mac80211: fix key...
594
  }
d4e46a3d9   Johannes Berg   [MAC80211]: fix r...
595

ad0e2b5a0   Johannes Berg   mac80211: simplif...
596
  void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
3a2457669   Johannes Berg   mac80211: fix key...
597
598
  {
  	struct ieee80211_key *key;
11a843b7e   Johannes Berg   [MAC80211]: rewor...
599

3a2457669   Johannes Berg   mac80211: fix key...
600
  	ASSERT_RTNL();
11a843b7e   Johannes Berg   [MAC80211]: rewor...
601

9607e6b66   Johannes Berg   mac80211: add iee...
602
  	if (WARN_ON(!ieee80211_sdata_running(sdata)))
3a2457669   Johannes Berg   mac80211: fix key...
603
  		return;
11a843b7e   Johannes Berg   [MAC80211]: rewor...
604

ad0e2b5a0   Johannes Berg   mac80211: simplif...
605
  	mutex_lock(&sdata->local->key_mtx);
11a843b7e   Johannes Berg   [MAC80211]: rewor...
606

3bff18651   Yogesh Ashok Powar   mac80211: Skip ta...
607
608
609
610
  	sdata->crypto_tx_tailroom_needed_cnt = 0;
  
  	list_for_each_entry(key, &sdata->key_list, list) {
  		increment_tailroom_need_count(sdata);
ad0e2b5a0   Johannes Berg   mac80211: simplif...
611
  		ieee80211_key_enable_hw_accel(key);
3bff18651   Yogesh Ashok Powar   mac80211: Skip ta...
612
  	}
3b96766f0   Johannes Berg   mac80211: fix key...
613

ad0e2b5a0   Johannes Berg   mac80211: simplif...
614
  	mutex_unlock(&sdata->local->key_mtx);
11a843b7e   Johannes Berg   [MAC80211]: rewor...
615
  }
830af02f2   Johannes Berg   mac80211: allow d...
616
617
618
619
620
621
622
623
624
625
  void ieee80211_iter_keys(struct ieee80211_hw *hw,
  			 struct ieee80211_vif *vif,
  			 void (*iter)(struct ieee80211_hw *hw,
  				      struct ieee80211_vif *vif,
  				      struct ieee80211_sta *sta,
  				      struct ieee80211_key_conf *key,
  				      void *data),
  			 void *iter_data)
  {
  	struct ieee80211_local *local = hw_to_local(hw);
27b3eb9c0   Johannes Berg   mac80211: add API...
626
  	struct ieee80211_key *key, *tmp;
830af02f2   Johannes Berg   mac80211: allow d...
627
628
629
630
631
632
633
  	struct ieee80211_sub_if_data *sdata;
  
  	ASSERT_RTNL();
  
  	mutex_lock(&local->key_mtx);
  	if (vif) {
  		sdata = vif_to_sdata(vif);
27b3eb9c0   Johannes Berg   mac80211: add API...
634
  		list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
830af02f2   Johannes Berg   mac80211: allow d...
635
636
637
638
639
  			iter(hw, &sdata->vif,
  			     key->sta ? &key->sta->sta : NULL,
  			     &key->conf, iter_data);
  	} else {
  		list_for_each_entry(sdata, &local->interfaces, list)
27b3eb9c0   Johannes Berg   mac80211: add API...
640
641
  			list_for_each_entry_safe(key, tmp,
  						 &sdata->key_list, list)
830af02f2   Johannes Berg   mac80211: allow d...
642
643
644
645
646
647
648
  				iter(hw, &sdata->vif,
  				     key->sta ? &key->sta->sta : NULL,
  				     &key->conf, iter_data);
  	}
  	mutex_unlock(&local->key_mtx);
  }
  EXPORT_SYMBOL(ieee80211_iter_keys);
7907c7d33   Johannes Berg   mac80211: free al...
649
650
  static void ieee80211_free_keys_iface(struct ieee80211_sub_if_data *sdata,
  				      struct list_head *keys)
3b96766f0   Johannes Berg   mac80211: fix key...
651
652
  {
  	struct ieee80211_key *key, *tmp;
3b96766f0   Johannes Berg   mac80211: fix key...
653

8d1f7ecd2   Johannes Berg   mac80211: defer t...
654
655
656
  	sdata->crypto_tx_tailroom_needed_cnt -=
  		sdata->crypto_tx_tailroom_pending_dec;
  	sdata->crypto_tx_tailroom_pending_dec = 0;
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
657
  	ieee80211_debugfs_key_remove_mgmt_default(sdata);
3b96766f0   Johannes Berg   mac80211: fix key...
658

6d10e46be   Johannes Berg   mac80211: batch k...
659
660
661
662
  	list_for_each_entry_safe(key, tmp, &sdata->key_list, list) {
  		ieee80211_key_replace(key->sdata, key->sta,
  				key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
  				key, NULL);
7907c7d33   Johannes Berg   mac80211: free al...
663
  		list_add_tail(&key->list, keys);
6d10e46be   Johannes Berg   mac80211: batch k...
664
  	}
3b96766f0   Johannes Berg   mac80211: fix key...
665

f7e0104c1   Johannes Berg   mac80211: support...
666
  	ieee80211_debugfs_key_update_default(sdata);
7907c7d33   Johannes Berg   mac80211: free al...
667
  }
f7e0104c1   Johannes Berg   mac80211: support...
668

7907c7d33   Johannes Berg   mac80211: free al...
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
  void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata,
  			 bool force_synchronize)
  {
  	struct ieee80211_local *local = sdata->local;
  	struct ieee80211_sub_if_data *vlan;
  	struct ieee80211_key *key, *tmp;
  	LIST_HEAD(keys);
  
  	cancel_delayed_work_sync(&sdata->dec_tailroom_needed_wk);
  
  	mutex_lock(&local->key_mtx);
  
  	ieee80211_free_keys_iface(sdata, &keys);
  
  	if (sdata->vif.type == NL80211_IFTYPE_AP) {
  		list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
  			ieee80211_free_keys_iface(vlan, &keys);
6d10e46be   Johannes Berg   mac80211: batch k...
686
  	}
7907c7d33   Johannes Berg   mac80211: free al...
687
688
689
690
  	if (!list_empty(&keys) || force_synchronize)
  		synchronize_net();
  	list_for_each_entry_safe(key, tmp, &keys, list)
  		__ieee80211_key_destroy(key, false);
8d1f7ecd2   Johannes Berg   mac80211: defer t...
691
692
  	WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt ||
  		     sdata->crypto_tx_tailroom_pending_dec);
7907c7d33   Johannes Berg   mac80211: free al...
693
694
695
696
697
  	if (sdata->vif.type == NL80211_IFTYPE_AP) {
  		list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
  			WARN_ON_ONCE(vlan->crypto_tx_tailroom_needed_cnt ||
  				     vlan->crypto_tx_tailroom_pending_dec);
  	}
8d1f7ecd2   Johannes Berg   mac80211: defer t...
698

7907c7d33   Johannes Berg   mac80211: free al...
699
  	mutex_unlock(&local->key_mtx);
11a843b7e   Johannes Berg   [MAC80211]: rewor...
700
  }
c68f4b892   Johannes Berg   mac80211: support...
701

6d10e46be   Johannes Berg   mac80211: batch k...
702
703
704
  void ieee80211_free_sta_keys(struct ieee80211_local *local,
  			     struct sta_info *sta)
  {
c87820784   Johannes Berg   mac80211: move sy...
705
  	struct ieee80211_key *key;
6d10e46be   Johannes Berg   mac80211: batch k...
706
707
708
  	int i;
  
  	mutex_lock(&local->key_mtx);
28a9bc681   Johannes Berg   mac80211: free ma...
709
  	for (i = 0; i < ARRAY_SIZE(sta->gtk); i++) {
6d10e46be   Johannes Berg   mac80211: batch k...
710
711
712
713
714
715
  		key = key_mtx_dereference(local, sta->gtk[i]);
  		if (!key)
  			continue;
  		ieee80211_key_replace(key->sdata, key->sta,
  				key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
  				key, NULL);
c87820784   Johannes Berg   mac80211: move sy...
716
  		__ieee80211_key_destroy(key, true);
6d10e46be   Johannes Berg   mac80211: batch k...
717
  	}
2475b1cc0   Max Stepanov   mac80211: add gen...
718
719
720
721
  	for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
  		key = key_mtx_dereference(local, sta->ptk[i]);
  		if (!key)
  			continue;
6d10e46be   Johannes Berg   mac80211: batch k...
722
723
724
  		ieee80211_key_replace(key->sdata, key->sta,
  				key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
  				key, NULL);
6d10e46be   Johannes Berg   mac80211: batch k...
725
  		__ieee80211_key_destroy(key, true);
c87820784   Johannes Berg   mac80211: move sy...
726
  	}
6d10e46be   Johannes Berg   mac80211: batch k...
727
728
729
  
  	mutex_unlock(&local->key_mtx);
  }
8d1f7ecd2   Johannes Berg   mac80211: defer t...
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
  void ieee80211_delayed_tailroom_dec(struct work_struct *wk)
  {
  	struct ieee80211_sub_if_data *sdata;
  
  	sdata = container_of(wk, struct ieee80211_sub_if_data,
  			     dec_tailroom_needed_wk.work);
  
  	/*
  	 * The reason for the delayed tailroom needed decrementing is to
  	 * make roaming faster: during roaming, all keys are first deleted
  	 * and then new keys are installed. The first new key causes the
  	 * crypto_tx_tailroom_needed_cnt to go from 0 to 1, which invokes
  	 * the cost of synchronize_net() (which can be slow). Avoid this
  	 * by deferring the crypto_tx_tailroom_needed_cnt decrementing on
  	 * key removal for a while, so if we roam the value is larger than
  	 * zero and no 0->1 transition happens.
  	 *
  	 * The cost is that if the AP switching was from an AP with keys
  	 * to one without, we still allocate tailroom while it would no
  	 * longer be needed. However, in the typical (fast) roaming case
  	 * within an ESS this usually won't happen.
  	 */
  
  	mutex_lock(&sdata->local->key_mtx);
  	sdata->crypto_tx_tailroom_needed_cnt -=
  		sdata->crypto_tx_tailroom_pending_dec;
  	sdata->crypto_tx_tailroom_pending_dec = 0;
  	mutex_unlock(&sdata->local->key_mtx);
  }
c68f4b892   Johannes Berg   mac80211: support...
759
760
761
762
763
764
765
766
767
768
769
  
  void ieee80211_gtk_rekey_notify(struct ieee80211_vif *vif, const u8 *bssid,
  				const u8 *replay_ctr, gfp_t gfp)
  {
  	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
  
  	trace_api_gtk_rekey_notify(sdata, bssid, replay_ctr);
  
  	cfg80211_gtk_rekey_notify(sdata->dev, bssid, replay_ctr, gfp);
  }
  EXPORT_SYMBOL_GPL(ieee80211_gtk_rekey_notify);
3ea542d3c   Johannes Berg   mac80211: allow d...
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
  
  void ieee80211_get_key_tx_seq(struct ieee80211_key_conf *keyconf,
  			      struct ieee80211_key_seq *seq)
  {
  	struct ieee80211_key *key;
  	u64 pn64;
  
  	if (WARN_ON(!(keyconf->flags & IEEE80211_KEY_FLAG_GENERATE_IV)))
  		return;
  
  	key = container_of(keyconf, struct ieee80211_key, conf);
  
  	switch (key->conf.cipher) {
  	case WLAN_CIPHER_SUITE_TKIP:
  		seq->tkip.iv32 = key->u.tkip.tx.iv32;
  		seq->tkip.iv16 = key->u.tkip.tx.iv16;
  		break;
  	case WLAN_CIPHER_SUITE_CCMP:
2b2ba0db1   Jouni Malinen   mac80111: Add CCM...
788
  	case WLAN_CIPHER_SUITE_CCMP_256:
3ea542d3c   Johannes Berg   mac80211: allow d...
789
790
791
792
793
794
795
796
797
  		pn64 = atomic64_read(&key->u.ccmp.tx_pn);
  		seq->ccmp.pn[5] = pn64;
  		seq->ccmp.pn[4] = pn64 >> 8;
  		seq->ccmp.pn[3] = pn64 >> 16;
  		seq->ccmp.pn[2] = pn64 >> 24;
  		seq->ccmp.pn[1] = pn64 >> 32;
  		seq->ccmp.pn[0] = pn64 >> 40;
  		break;
  	case WLAN_CIPHER_SUITE_AES_CMAC:
56c52da2d   Jouni Malinen   mac80111: Add BIP...
798
  	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
3ea542d3c   Johannes Berg   mac80211: allow d...
799
800
801
802
803
804
805
806
  		pn64 = atomic64_read(&key->u.aes_cmac.tx_pn);
  		seq->ccmp.pn[5] = pn64;
  		seq->ccmp.pn[4] = pn64 >> 8;
  		seq->ccmp.pn[3] = pn64 >> 16;
  		seq->ccmp.pn[2] = pn64 >> 24;
  		seq->ccmp.pn[1] = pn64 >> 32;
  		seq->ccmp.pn[0] = pn64 >> 40;
  		break;
8ade538bf   Jouni Malinen   mac80111: Add BIP...
807
808
809
810
811
812
813
814
815
816
  	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
  	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
  		pn64 = atomic64_read(&key->u.aes_gmac.tx_pn);
  		seq->ccmp.pn[5] = pn64;
  		seq->ccmp.pn[4] = pn64 >> 8;
  		seq->ccmp.pn[3] = pn64 >> 16;
  		seq->ccmp.pn[2] = pn64 >> 24;
  		seq->ccmp.pn[1] = pn64 >> 32;
  		seq->ccmp.pn[0] = pn64 >> 40;
  		break;
00b9cfa3f   Jouni Malinen   mac80111: Add GCM...
817
818
819
820
821
822
823
824
825
826
  	case WLAN_CIPHER_SUITE_GCMP:
  	case WLAN_CIPHER_SUITE_GCMP_256:
  		pn64 = atomic64_read(&key->u.gcmp.tx_pn);
  		seq->gcmp.pn[5] = pn64;
  		seq->gcmp.pn[4] = pn64 >> 8;
  		seq->gcmp.pn[3] = pn64 >> 16;
  		seq->gcmp.pn[2] = pn64 >> 24;
  		seq->gcmp.pn[1] = pn64 >> 32;
  		seq->gcmp.pn[0] = pn64 >> 40;
  		break;
3ea542d3c   Johannes Berg   mac80211: allow d...
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
  	default:
  		WARN_ON(1);
  	}
  }
  EXPORT_SYMBOL(ieee80211_get_key_tx_seq);
  
  void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf,
  			      int tid, struct ieee80211_key_seq *seq)
  {
  	struct ieee80211_key *key;
  	const u8 *pn;
  
  	key = container_of(keyconf, struct ieee80211_key, conf);
  
  	switch (key->conf.cipher) {
  	case WLAN_CIPHER_SUITE_TKIP:
5a306f588   Johannes Berg   mac80211: introdu...
843
  		if (WARN_ON(tid < 0 || tid >= IEEE80211_NUM_TIDS))
3ea542d3c   Johannes Berg   mac80211: allow d...
844
845
846
847
848
  			return;
  		seq->tkip.iv32 = key->u.tkip.rx[tid].iv32;
  		seq->tkip.iv16 = key->u.tkip.rx[tid].iv16;
  		break;
  	case WLAN_CIPHER_SUITE_CCMP:
2b2ba0db1   Jouni Malinen   mac80111: Add CCM...
849
  	case WLAN_CIPHER_SUITE_CCMP_256:
5a306f588   Johannes Berg   mac80211: introdu...
850
  		if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS))
3ea542d3c   Johannes Berg   mac80211: allow d...
851
852
  			return;
  		if (tid < 0)
5a306f588   Johannes Berg   mac80211: introdu...
853
  			pn = key->u.ccmp.rx_pn[IEEE80211_NUM_TIDS];
3ea542d3c   Johannes Berg   mac80211: allow d...
854
855
  		else
  			pn = key->u.ccmp.rx_pn[tid];
4325f6caa   Johannes Berg   wireless: move cr...
856
  		memcpy(seq->ccmp.pn, pn, IEEE80211_CCMP_PN_LEN);
3ea542d3c   Johannes Berg   mac80211: allow d...
857
858
  		break;
  	case WLAN_CIPHER_SUITE_AES_CMAC:
56c52da2d   Jouni Malinen   mac80111: Add BIP...
859
  	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
3ea542d3c   Johannes Berg   mac80211: allow d...
860
861
862
  		if (WARN_ON(tid != 0))
  			return;
  		pn = key->u.aes_cmac.rx_pn;
4325f6caa   Johannes Berg   wireless: move cr...
863
  		memcpy(seq->aes_cmac.pn, pn, IEEE80211_CMAC_PN_LEN);
3ea542d3c   Johannes Berg   mac80211: allow d...
864
  		break;
8ade538bf   Jouni Malinen   mac80111: Add BIP...
865
866
867
868
869
870
871
  	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
  	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
  		if (WARN_ON(tid != 0))
  			return;
  		pn = key->u.aes_gmac.rx_pn;
  		memcpy(seq->aes_gmac.pn, pn, IEEE80211_GMAC_PN_LEN);
  		break;
00b9cfa3f   Jouni Malinen   mac80111: Add GCM...
872
873
874
875
876
877
878
879
880
881
  	case WLAN_CIPHER_SUITE_GCMP:
  	case WLAN_CIPHER_SUITE_GCMP_256:
  		if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS))
  			return;
  		if (tid < 0)
  			pn = key->u.gcmp.rx_pn[IEEE80211_NUM_TIDS];
  		else
  			pn = key->u.gcmp.rx_pn[tid];
  		memcpy(seq->gcmp.pn, pn, IEEE80211_GCMP_PN_LEN);
  		break;
3ea542d3c   Johannes Berg   mac80211: allow d...
882
883
884
  	}
  }
  EXPORT_SYMBOL(ieee80211_get_key_rx_seq);
27b3eb9c0   Johannes Berg   mac80211: add API...
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
  
  void ieee80211_set_key_tx_seq(struct ieee80211_key_conf *keyconf,
  			      struct ieee80211_key_seq *seq)
  {
  	struct ieee80211_key *key;
  	u64 pn64;
  
  	key = container_of(keyconf, struct ieee80211_key, conf);
  
  	switch (key->conf.cipher) {
  	case WLAN_CIPHER_SUITE_TKIP:
  		key->u.tkip.tx.iv32 = seq->tkip.iv32;
  		key->u.tkip.tx.iv16 = seq->tkip.iv16;
  		break;
  	case WLAN_CIPHER_SUITE_CCMP:
2b2ba0db1   Jouni Malinen   mac80111: Add CCM...
900
  	case WLAN_CIPHER_SUITE_CCMP_256:
27b3eb9c0   Johannes Berg   mac80211: add API...
901
902
903
904
905
906
907
908
909
  		pn64 = (u64)seq->ccmp.pn[5] |
  		       ((u64)seq->ccmp.pn[4] << 8) |
  		       ((u64)seq->ccmp.pn[3] << 16) |
  		       ((u64)seq->ccmp.pn[2] << 24) |
  		       ((u64)seq->ccmp.pn[1] << 32) |
  		       ((u64)seq->ccmp.pn[0] << 40);
  		atomic64_set(&key->u.ccmp.tx_pn, pn64);
  		break;
  	case WLAN_CIPHER_SUITE_AES_CMAC:
56c52da2d   Jouni Malinen   mac80111: Add BIP...
910
  	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
27b3eb9c0   Johannes Berg   mac80211: add API...
911
912
913
914
915
916
917
918
  		pn64 = (u64)seq->aes_cmac.pn[5] |
  		       ((u64)seq->aes_cmac.pn[4] << 8) |
  		       ((u64)seq->aes_cmac.pn[3] << 16) |
  		       ((u64)seq->aes_cmac.pn[2] << 24) |
  		       ((u64)seq->aes_cmac.pn[1] << 32) |
  		       ((u64)seq->aes_cmac.pn[0] << 40);
  		atomic64_set(&key->u.aes_cmac.tx_pn, pn64);
  		break;
8ade538bf   Jouni Malinen   mac80111: Add BIP...
919
920
921
922
923
924
925
926
927
928
  	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
  	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
  		pn64 = (u64)seq->aes_gmac.pn[5] |
  		       ((u64)seq->aes_gmac.pn[4] << 8) |
  		       ((u64)seq->aes_gmac.pn[3] << 16) |
  		       ((u64)seq->aes_gmac.pn[2] << 24) |
  		       ((u64)seq->aes_gmac.pn[1] << 32) |
  		       ((u64)seq->aes_gmac.pn[0] << 40);
  		atomic64_set(&key->u.aes_gmac.tx_pn, pn64);
  		break;
00b9cfa3f   Jouni Malinen   mac80111: Add GCM...
929
930
931
932
933
934
935
936
937
938
  	case WLAN_CIPHER_SUITE_GCMP:
  	case WLAN_CIPHER_SUITE_GCMP_256:
  		pn64 = (u64)seq->gcmp.pn[5] |
  		       ((u64)seq->gcmp.pn[4] << 8) |
  		       ((u64)seq->gcmp.pn[3] << 16) |
  		       ((u64)seq->gcmp.pn[2] << 24) |
  		       ((u64)seq->gcmp.pn[1] << 32) |
  		       ((u64)seq->gcmp.pn[0] << 40);
  		atomic64_set(&key->u.gcmp.tx_pn, pn64);
  		break;
27b3eb9c0   Johannes Berg   mac80211: add API...
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
  	default:
  		WARN_ON(1);
  		break;
  	}
  }
  EXPORT_SYMBOL_GPL(ieee80211_set_key_tx_seq);
  
  void ieee80211_set_key_rx_seq(struct ieee80211_key_conf *keyconf,
  			      int tid, struct ieee80211_key_seq *seq)
  {
  	struct ieee80211_key *key;
  	u8 *pn;
  
  	key = container_of(keyconf, struct ieee80211_key, conf);
  
  	switch (key->conf.cipher) {
  	case WLAN_CIPHER_SUITE_TKIP:
  		if (WARN_ON(tid < 0 || tid >= IEEE80211_NUM_TIDS))
  			return;
  		key->u.tkip.rx[tid].iv32 = seq->tkip.iv32;
  		key->u.tkip.rx[tid].iv16 = seq->tkip.iv16;
  		break;
  	case WLAN_CIPHER_SUITE_CCMP:
2b2ba0db1   Jouni Malinen   mac80111: Add CCM...
962
  	case WLAN_CIPHER_SUITE_CCMP_256:
27b3eb9c0   Johannes Berg   mac80211: add API...
963
964
965
966
967
968
969
970
971
  		if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS))
  			return;
  		if (tid < 0)
  			pn = key->u.ccmp.rx_pn[IEEE80211_NUM_TIDS];
  		else
  			pn = key->u.ccmp.rx_pn[tid];
  		memcpy(pn, seq->ccmp.pn, IEEE80211_CCMP_PN_LEN);
  		break;
  	case WLAN_CIPHER_SUITE_AES_CMAC:
56c52da2d   Jouni Malinen   mac80111: Add BIP...
972
  	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
27b3eb9c0   Johannes Berg   mac80211: add API...
973
974
975
976
977
  		if (WARN_ON(tid != 0))
  			return;
  		pn = key->u.aes_cmac.rx_pn;
  		memcpy(pn, seq->aes_cmac.pn, IEEE80211_CMAC_PN_LEN);
  		break;
8ade538bf   Jouni Malinen   mac80111: Add BIP...
978
979
980
981
982
983
984
  	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
  	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
  		if (WARN_ON(tid != 0))
  			return;
  		pn = key->u.aes_gmac.rx_pn;
  		memcpy(pn, seq->aes_gmac.pn, IEEE80211_GMAC_PN_LEN);
  		break;
00b9cfa3f   Jouni Malinen   mac80111: Add GCM...
985
986
987
988
989
990
991
992
993
994
  	case WLAN_CIPHER_SUITE_GCMP:
  	case WLAN_CIPHER_SUITE_GCMP_256:
  		if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS))
  			return;
  		if (tid < 0)
  			pn = key->u.gcmp.rx_pn[IEEE80211_NUM_TIDS];
  		else
  			pn = key->u.gcmp.rx_pn[tid];
  		memcpy(pn, seq->gcmp.pn, IEEE80211_GCMP_PN_LEN);
  		break;
27b3eb9c0   Johannes Berg   mac80211: add API...
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
  	default:
  		WARN_ON(1);
  		break;
  	}
  }
  EXPORT_SYMBOL_GPL(ieee80211_set_key_rx_seq);
  
  void ieee80211_remove_key(struct ieee80211_key_conf *keyconf)
  {
  	struct ieee80211_key *key;
  
  	key = container_of(keyconf, struct ieee80211_key, conf);
  
  	assert_key_lock(key->local);
  
  	/*
  	 * if key was uploaded, we assume the driver will/has remove(d)
  	 * it, so adjust bookkeeping accordingly
  	 */
  	if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
  		key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
1e359a5de   Johannes Berg   Revert "mac80211:...
1016
  		if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
db12847ca   Ido Yariv   mac80211: Re-fix ...
1017
  		      (key->conf.flags & IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
27b3eb9c0   Johannes Berg   mac80211: add API...
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
  			increment_tailroom_need_count(key->sdata);
  	}
  
  	ieee80211_key_free(key, false);
  }
  EXPORT_SYMBOL_GPL(ieee80211_remove_key);
  
  struct ieee80211_key_conf *
  ieee80211_gtk_rekey_add(struct ieee80211_vif *vif,
  			struct ieee80211_key_conf *keyconf)
  {
  	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
  	struct ieee80211_local *local = sdata->local;
  	struct ieee80211_key *key;
  	int err;
  
  	if (WARN_ON(!local->wowlan))
  		return ERR_PTR(-EINVAL);
  
  	if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
  		return ERR_PTR(-EINVAL);
  
  	key = ieee80211_key_alloc(keyconf->cipher, keyconf->keyidx,
  				  keyconf->keylen, keyconf->key,
2475b1cc0   Max Stepanov   mac80211: add gen...
1042
  				  0, NULL, NULL);
27b3eb9c0   Johannes Berg   mac80211: add API...
1043
  	if (IS_ERR(key))
c5dc164df   Johannes Berg   mac80211: use ERR...
1044
  		return ERR_CAST(key);
27b3eb9c0   Johannes Berg   mac80211: add API...
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
  
  	if (sdata->u.mgd.mfp != IEEE80211_MFP_DISABLED)
  		key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT;
  
  	err = ieee80211_key_link(key, sdata, NULL);
  	if (err)
  		return ERR_PTR(err);
  
  	return &key->conf;
  }
  EXPORT_SYMBOL_GPL(ieee80211_gtk_rekey_add);