Blame view

net/mac80211/key.c 35 KB
d2912cb15   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
1f5a7e47a   Johannes Berg   [MAC80211]: split...
2
3
4
5
  /*
   * 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...
6
   * Copyright 2007-2008	Johannes Berg <johannes@sipsolutions.net>
d98ad83ee   Johannes Berg   mac80211: add Int...
7
   * Copyright 2013-2014  Intel Mobile Communications GmbH
fdf7cb418   Johannes Berg   mac80211: accept ...
8
   * Copyright 2015-2017	Intel Deutschland GmbH
1c9559734   Johannes Berg   mac80211: remove ...
9
   * Copyright 2018-2019  Intel Corporation
1f5a7e47a   Johannes Berg   [MAC80211]: split...
10
   */
11a843b7e   Johannes Berg   [MAC80211]: rewor...
11
12
13
  #include <linux/if_ether.h>
  #include <linux/etherdevice.h>
  #include <linux/list.h>
d4e46a3d9   Johannes Berg   [MAC80211]: fix r...
14
  #include <linux/rcupdate.h>
db4d1169d   Johannes Berg   mac80211: split i...
15
  #include <linux/rtnetlink.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
16
  #include <linux/slab.h>
bc3b2d7fb   Paul Gortmaker   net: Add export.h...
17
  #include <linux/export.h>
1f5a7e47a   Johannes Berg   [MAC80211]: split...
18
  #include <net/mac80211.h>
2bdd713b9   Jason A. Donenfeld   mac80211: use con...
19
  #include <crypto/algapi.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
  }
f9dca80b9   Michal Kazior   mac80211: fix AP_...
59
60
61
62
63
64
65
  static void
  update_vlan_tailroom_need_count(struct ieee80211_sub_if_data *sdata, int delta)
  {
  	struct ieee80211_sub_if_data *vlan;
  
  	if (sdata->vif.type != NL80211_IFTYPE_AP)
  		return;
51f458d96   Johannes Berg   mac80211: fix loc...
66
67
  	/* crypto_tx_tailroom_needed_cnt is protected by this */
  	assert_key_lock(sdata->local);
f9dca80b9   Michal Kazior   mac80211: fix AP_...
68

51f458d96   Johannes Berg   mac80211: fix loc...
69
70
71
  	rcu_read_lock();
  
  	list_for_each_entry_rcu(vlan, &sdata->u.ap.vlans, u.vlan.list)
f9dca80b9   Michal Kazior   mac80211: fix AP_...
72
  		vlan->crypto_tx_tailroom_needed_cnt += delta;
51f458d96   Johannes Berg   mac80211: fix loc...
73
  	rcu_read_unlock();
f9dca80b9   Michal Kazior   mac80211: fix AP_...
74
  }
3bff18651   Yogesh Ashok Powar   mac80211: Skip ta...
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
  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
  	 */
51f458d96   Johannes Berg   mac80211: fix loc...
95
  	assert_key_lock(sdata->local);
f9dca80b9   Michal Kazior   mac80211: fix AP_...
96
  	update_vlan_tailroom_need_count(sdata, 1);
3bff18651   Yogesh Ashok Powar   mac80211: Skip ta...
97
98
99
100
101
102
103
104
  	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();
  	}
  }
f9dca80b9   Michal Kazior   mac80211: fix AP_...
105
106
107
  static void decrease_tailroom_need_count(struct ieee80211_sub_if_data *sdata,
  					 int delta)
  {
51f458d96   Johannes Berg   mac80211: fix loc...
108
  	assert_key_lock(sdata->local);
f9dca80b9   Michal Kazior   mac80211: fix AP_...
109
110
111
112
113
  	WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt < delta);
  
  	update_vlan_tailroom_need_count(sdata, -delta);
  	sdata->crypto_tx_tailroom_needed_cnt -= delta;
  }
3ffc2a905   Johannes Berg   mac80211: allow v...
114
  static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
11a843b7e   Johannes Berg   [MAC80211]: rewor...
115
  {
db3bdcb9c   Manikanta Pubbisetty   mac80211: allow A...
116
  	struct ieee80211_sub_if_data *sdata = key->sdata;
89c91caec   Johannes Berg   mac80211: dont pr...
117
  	struct sta_info *sta;
fa7e1fbcb   Johannes Berg   mac80211: allow d...
118
  	int ret = -EOPNOTSUPP;
11a843b7e   Johannes Berg   [MAC80211]: rewor...
119

3b96766f0   Johannes Berg   mac80211: fix key...
120
  	might_sleep();
4619194a4   Johannes Berg   mac80211: don't r...
121
122
123
124
125
126
127
128
  	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.
  		 */
092c4098f   Alexander Wetzel   mac80211: Optimiz...
129
130
131
132
133
  		if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE &&
  		    !(key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
  					 IEEE80211_KEY_FLAG_PUT_MIC_SPACE |
  					 IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
  			increment_tailroom_need_count(sdata);
4619194a4   Johannes Berg   mac80211: don't r...
134
  		key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
27b3eb9c0   Johannes Berg   mac80211: add API...
135
  		return -EINVAL;
4619194a4   Johannes Berg   mac80211: don't r...
136
  	}
27b3eb9c0   Johannes Berg   mac80211: add API...
137

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

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

e31b82136   Johannes Berg   cfg80211/mac80211...
144
145
146
147
148
  	/*
  	 * If this is a per-STA GTK, check if it
  	 * is supported; if not, return.
  	 */
  	if (sta && !(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE) &&
30686bf7f   Johannes Berg   mac80211: convert...
149
  	    !ieee80211_hw_check(&key->local->hw, SUPPORTS_PER_STA_GTK))
e31b82136   Johannes Berg   cfg80211/mac80211...
150
  		goto out_unsupported;
89c91caec   Johannes Berg   mac80211: dont pr...
151
152
  	if (sta && !sta->uploaded)
  		goto out_unsupported;
18890d4b8   Helmut Schaa   mac80211: Disable...
153
154
155
156
157
  	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.
  		 */
78ad23415   Alexander Wetzel   mac80211: Honor S...
158
159
  		if (!(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
  			ret = 1;
18890d4b8   Helmut Schaa   mac80211: Disable...
160
  			goto out_unsupported;
78ad23415   Alexander Wetzel   mac80211: Honor S...
161
  		}
18890d4b8   Helmut Schaa   mac80211: Disable...
162
  	}
11a843b7e   Johannes Berg   [MAC80211]: rewor...
163

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

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

092c4098f   Alexander Wetzel   mac80211: Optimiz...
170
171
172
  		if (!(key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
  					 IEEE80211_KEY_FLAG_PUT_MIC_SPACE |
  					 IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
f9dca80b9   Michal Kazior   mac80211: fix AP_...
173
  			decrease_tailroom_need_count(sdata, 1);
3bff18651   Yogesh Ashok Powar   mac80211: Skip ta...
174

077a91548   Arik Nemtsov   mac80211: support...
175
176
  		WARN_ON((key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE) &&
  			(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV));
9de18d818   David Spinadel   mac80211: Add MIC...
177
178
  		WARN_ON((key->conf.flags & IEEE80211_KEY_FLAG_PUT_MIC_SPACE) &&
  			(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC));
e31b82136   Johannes Berg   cfg80211/mac80211...
179
180
  		return 0;
  	}
11a843b7e   Johannes Berg   [MAC80211]: rewor...
181

fa7e1fbcb   Johannes Berg   mac80211: allow d...
182
  	if (ret != -ENOSPC && ret != -EOPNOTSUPP && ret != 1)
bdcbd8e0e   Johannes Berg   mac80211: clean u...
183
  		sdata_err(sdata,
0fb9a9ec2   Joe Perches   net/mac80211: Use...
184
185
  			  "failed to set key (%d, %pM) to hardware (%d)
  ",
89c91caec   Johannes Berg   mac80211: dont pr...
186
187
  			  key->conf.keyidx,
  			  sta ? sta->sta.addr : bcast_addr, ret);
3ffc2a905   Johannes Berg   mac80211: allow v...
188

e31b82136   Johannes Berg   cfg80211/mac80211...
189
190
191
192
193
194
   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...
195
  	case WLAN_CIPHER_SUITE_CCMP_256:
e31b82136   Johannes Berg   cfg80211/mac80211...
196
  	case WLAN_CIPHER_SUITE_AES_CMAC:
56c52da2d   Jouni Malinen   mac80111: Add BIP...
197
  	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
8ade538bf   Jouni Malinen   mac80111: Add BIP...
198
199
  	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
  	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
00b9cfa3f   Jouni Malinen   mac80111: Add GCM...
200
201
  	case WLAN_CIPHER_SUITE_GCMP:
  	case WLAN_CIPHER_SUITE_GCMP_256:
fa7e1fbcb   Johannes Berg   mac80211: allow d...
202
203
204
  		/* all of these we can do in software - if driver can */
  		if (ret == 1)
  			return 0;
78ad23415   Alexander Wetzel   mac80211: Honor S...
205
  		if (ieee80211_hw_check(&key->local->hw, SW_CRYPTO_CONTROL))
fa7e1fbcb   Johannes Berg   mac80211: allow d...
206
  			return -EINVAL;
e31b82136   Johannes Berg   cfg80211/mac80211...
207
208
209
  		return 0;
  	default:
  		return -EINVAL;
3ffc2a905   Johannes Berg   mac80211: allow v...
210
  	}
11a843b7e   Johannes Berg   [MAC80211]: rewor...
211
212
213
214
  }
  
  static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
  {
dc822b5db   Johannes Berg   mac80211: clean u...
215
  	struct ieee80211_sub_if_data *sdata;
89c91caec   Johannes Berg   mac80211: dont pr...
216
  	struct sta_info *sta;
11a843b7e   Johannes Berg   [MAC80211]: rewor...
217
  	int ret;
3b96766f0   Johannes Berg   mac80211: fix key...
218
  	might_sleep();
db4d1169d   Johannes Berg   mac80211: split i...
219
  	if (!key || !key->local->ops->set_key)
11a843b7e   Johannes Berg   [MAC80211]: rewor...
220
  		return;
ad0e2b5a0   Johannes Berg   mac80211: simplif...
221
222
223
  	assert_key_lock(key->local);
  
  	if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
11a843b7e   Johannes Berg   [MAC80211]: rewor...
224
  		return;
89c91caec   Johannes Berg   mac80211: dont pr...
225
  	sta = key->sta;
dc822b5db   Johannes Berg   mac80211: clean u...
226
  	sdata = key->sdata;
092c4098f   Alexander Wetzel   mac80211: Optimiz...
227
228
229
  	if (!(key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
  				 IEEE80211_KEY_FLAG_PUT_MIC_SPACE |
  				 IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
3bff18651   Yogesh Ashok Powar   mac80211: Skip ta...
230
  		increment_tailroom_need_count(sdata);
62872a9b9   Alexander Wetzel   mac80211: Fix PTK...
231
  	key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
12375ef93   Johannes Berg   mac80211: trace i...
232
  	ret = drv_set_key(key->local, DISABLE_KEY, sdata,
89c91caec   Johannes Berg   mac80211: dont pr...
233
  			  sta ? &sta->sta : NULL, &key->conf);
11a843b7e   Johannes Berg   [MAC80211]: rewor...
234
235
  
  	if (ret)
bdcbd8e0e   Johannes Berg   mac80211: clean u...
236
  		sdata_err(sdata,
0fb9a9ec2   Joe Perches   net/mac80211: Use...
237
238
  			  "failed to remove key (%d, %pM) from hardware (%d)
  ",
89c91caec   Johannes Berg   mac80211: dont pr...
239
240
  			  key->conf.keyidx,
  			  sta ? sta->sta.addr : bcast_addr, ret);
62872a9b9   Alexander Wetzel   mac80211: Fix PTK...
241
  }
11a843b7e   Johannes Berg   [MAC80211]: rewor...
242

96fc6efb9   Alexander Wetzel   mac80211: IEEE 80...
243
244
245
246
  int ieee80211_set_tx_key(struct ieee80211_key *key)
  {
  	struct sta_info *sta = key->sta;
  	struct ieee80211_local *local = key->local;
96fc6efb9   Alexander Wetzel   mac80211: IEEE 80...
247
248
  
  	assert_key_lock(local);
96fc6efb9   Alexander Wetzel   mac80211: IEEE 80...
249
  	sta->ptk_idx = key->conf.keyidx;
90cc4bd61   Alexander Wetzel   mac80211: AMPDU h...
250

dc3998ec5   Alexander Wetzel   mac80211: AMPDU h...
251
252
  	if (!ieee80211_hw_check(&local->hw, AMPDU_KEYBORDER_SUPPORT))
  		clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
96fc6efb9   Alexander Wetzel   mac80211: IEEE 80...
253
254
255
256
  	ieee80211_check_fast_xmit(sta);
  
  	return 0;
  }
90cc4bd61   Alexander Wetzel   mac80211: AMPDU h...
257
258
  static void ieee80211_pairwise_rekey(struct ieee80211_key *old,
  				     struct ieee80211_key *new)
62872a9b9   Alexander Wetzel   mac80211: Fix PTK...
259
  {
90cc4bd61   Alexander Wetzel   mac80211: AMPDU h...
260
261
262
  	struct ieee80211_local *local = new->local;
  	struct sta_info *sta = new->sta;
  	int i;
62872a9b9   Alexander Wetzel   mac80211: Fix PTK...
263

90cc4bd61   Alexander Wetzel   mac80211: AMPDU h...
264
  	assert_key_lock(local);
62872a9b9   Alexander Wetzel   mac80211: Fix PTK...
265

90cc4bd61   Alexander Wetzel   mac80211: AMPDU h...
266
267
  	if (new->conf.flags & IEEE80211_KEY_FLAG_NO_AUTO_TX) {
  		/* Extended Key ID key install, initial one or rekey */
dc3998ec5   Alexander Wetzel   mac80211: AMPDU h...
268
269
  		if (sta->ptk_idx != INVALID_PTK_KEYIDX &&
  		    !ieee80211_hw_check(&local->hw, AMPDU_KEYBORDER_SUPPORT)) {
90cc4bd61   Alexander Wetzel   mac80211: AMPDU h...
270
271
  			/* Aggregation Sessions with Extended Key ID must not
  			 * mix MPDUs with different keyIDs within one A-MPDU.
3e47bf1ca   Alexander Wetzel   mac80211: Simplif...
272
273
  			 * Tear down running Tx aggregation sessions and block
  			 * new Rx/Tx aggregation requests during rekey to
dc3998ec5   Alexander Wetzel   mac80211: AMPDU h...
274
275
276
277
  			 * ensure there are no A-MPDUs when the driver is not
  			 * supporting A-MPDU key borders. (Blocking Tx only
  			 * would be sufficient but WLAN_STA_BLOCK_BA gets the
  			 * job done for the few ms we need it.)
90cc4bd61   Alexander Wetzel   mac80211: AMPDU h...
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
  			 */
  			set_sta_flag(sta, WLAN_STA_BLOCK_BA);
  			mutex_lock(&sta->ampdu_mlme.mtx);
  			for (i = 0; i <  IEEE80211_NUM_TIDS; i++)
  				___ieee80211_stop_tx_ba_session(sta, i,
  								AGG_STOP_LOCAL_REQUEST);
  			mutex_unlock(&sta->ampdu_mlme.mtx);
  		}
  	} else if (old) {
  		/* Rekey without Extended Key ID.
  		 * Aggregation sessions are OK when running on SW crypto.
  		 * A broken remote STA may cause issues not observed with HW
  		 * crypto, though.
  		 */
  		if (!(old->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
  			return;
62872a9b9   Alexander Wetzel   mac80211: Fix PTK...
294

90cc4bd61   Alexander Wetzel   mac80211: AMPDU h...
295
296
  		/* Stop Tx till we are on the new key */
  		old->flags |= KEY_FLAG_TAINTED;
62872a9b9   Alexander Wetzel   mac80211: Fix PTK...
297
  		ieee80211_clear_fast_xmit(sta);
62872a9b9   Alexander Wetzel   mac80211: Fix PTK...
298
299
300
301
302
  		if (ieee80211_hw_check(&local->hw, AMPDU_AGGREGATION)) {
  			set_sta_flag(sta, WLAN_STA_BLOCK_BA);
  			ieee80211_sta_tear_down_BA_sessions(sta,
  							    AGG_STOP_LOCAL_REQUEST);
  		}
62872a9b9   Alexander Wetzel   mac80211: Fix PTK...
303
304
305
306
307
308
309
  		if (!wiphy_ext_feature_isset(local->hw.wiphy,
  					     NL80211_EXT_FEATURE_CAN_REPLACE_PTK0)) {
  			pr_warn_ratelimited("Rekeying PTK for STA %pM but driver can't safely do that.",
  					    sta->sta.addr);
  			/* Flushing the driver queues *may* help prevent
  			 * the clear text leaks and freezes.
  			 */
90cc4bd61   Alexander Wetzel   mac80211: AMPDU h...
310
  			ieee80211_flush_queues(local, old->sdata, false);
62872a9b9   Alexander Wetzel   mac80211: Fix PTK...
311
312
  		}
  	}
3b96766f0   Johannes Berg   mac80211: fix key...
313
314
315
  }
  
  static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
f7e0104c1   Johannes Berg   mac80211: support...
316
  					int idx, bool uni, bool multi)
3b96766f0   Johannes Berg   mac80211: fix key...
317
318
  {
  	struct ieee80211_key *key = NULL;
ad0e2b5a0   Johannes Berg   mac80211: simplif...
319
  	assert_key_lock(sdata->local);
3b96766f0   Johannes Berg   mac80211: fix key...
320
  	if (idx >= 0 && idx < NUM_DEFAULT_KEYS)
40b275b69   Johannes Berg   mac80211: sparse ...
321
  		key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
3b96766f0   Johannes Berg   mac80211: fix key...
322

de5fad815   Yoni Divinsky   mac80211: add op ...
323
  	if (uni) {
f7e0104c1   Johannes Berg   mac80211: support...
324
  		rcu_assign_pointer(sdata->default_unicast_key, key);
17c18bf88   Johannes Berg   mac80211: add TX ...
325
  		ieee80211_check_fast_xmit_iface(sdata);
ec4efc4a1   Johannes Berg   mac80211: don't c...
326
327
  		if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN)
  			drv_set_default_unicast_key(sdata->local, sdata, idx);
de5fad815   Yoni Divinsky   mac80211: add op ...
328
  	}
f7e0104c1   Johannes Berg   mac80211: support...
329
330
  	if (multi)
  		rcu_assign_pointer(sdata->default_multicast_key, key);
3b96766f0   Johannes Berg   mac80211: fix key...
331

f7e0104c1   Johannes Berg   mac80211: support...
332
  	ieee80211_debugfs_key_update_default(sdata);
3b96766f0   Johannes Berg   mac80211: fix key...
333
  }
f7e0104c1   Johannes Berg   mac80211: support...
334
335
  void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx,
  			       bool uni, bool multi)
3b96766f0   Johannes Berg   mac80211: fix key...
336
  {
ad0e2b5a0   Johannes Berg   mac80211: simplif...
337
  	mutex_lock(&sdata->local->key_mtx);
f7e0104c1   Johannes Berg   mac80211: support...
338
  	__ieee80211_set_default_key(sdata, idx, uni, multi);
ad0e2b5a0   Johannes Berg   mac80211: simplif...
339
  	mutex_unlock(&sdata->local->key_mtx);
3b96766f0   Johannes Berg   mac80211: fix key...
340
  }
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
341
342
343
344
  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...
345
  	assert_key_lock(sdata->local);
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
346
347
  	if (idx >= NUM_DEFAULT_KEYS &&
  	    idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
40b275b69   Johannes Berg   mac80211: sparse ...
348
  		key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
349
350
  
  	rcu_assign_pointer(sdata->default_mgmt_key, key);
f7e0104c1   Johannes Berg   mac80211: support...
351
  	ieee80211_debugfs_key_update_default(sdata);
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
352
353
354
355
356
  }
  
  void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
  				    int idx)
  {
ad0e2b5a0   Johannes Berg   mac80211: simplif...
357
  	mutex_lock(&sdata->local->key_mtx);
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
358
  	__ieee80211_set_default_mgmt_key(sdata, idx);
ad0e2b5a0   Johannes Berg   mac80211: simplif...
359
  	mutex_unlock(&sdata->local->key_mtx);
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
360
  }
62872a9b9   Alexander Wetzel   mac80211: Fix PTK...
361
  static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
3b8d9c290   Johannes Berg   mac80211: remove ...
362
363
364
365
  				  struct sta_info *sta,
  				  bool pairwise,
  				  struct ieee80211_key *old,
  				  struct ieee80211_key *new)
3b96766f0   Johannes Berg   mac80211: fix key...
366
  {
f7e0104c1   Johannes Berg   mac80211: support...
367
  	int idx;
90cc4bd61   Alexander Wetzel   mac80211: AMPDU h...
368
  	int ret = 0;
f7e0104c1   Johannes Berg   mac80211: support...
369
  	bool defunikey, defmultikey, defmgmtkey;
3b96766f0   Johannes Berg   mac80211: fix key...
370

5282c3ba4   Johannes Berg   mac80211: verify ...
371
372
  	/* caller must provide at least one old/new */
  	if (WARN_ON(!new && !old))
62872a9b9   Alexander Wetzel   mac80211: Fix PTK...
373
  		return 0;
5282c3ba4   Johannes Berg   mac80211: verify ...
374

3b96766f0   Johannes Berg   mac80211: fix key...
375
  	if (new)
ef044763a   Eliad Peller   mac80211: add ato...
376
  		list_add_tail_rcu(&new->list, &sdata->key_list);
3b96766f0   Johannes Berg   mac80211: fix key...
377

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

90cc4bd61   Alexander Wetzel   mac80211: AMPDU h...
380
381
382
383
384
385
  	if (new && sta && pairwise) {
  		/* Unicast rekey needs special handling. With Extended Key ID
  		 * old is still NULL for the first rekey.
  		 */
  		ieee80211_pairwise_rekey(old, new);
  	}
62872a9b9   Alexander Wetzel   mac80211: Fix PTK...
386
  	if (old) {
2475b1cc0   Max Stepanov   mac80211: add gen...
387
  		idx = old->conf.keyidx;
90cc4bd61   Alexander Wetzel   mac80211: AMPDU h...
388
389
390
391
392
393
394
  
  		if (old->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
  			ieee80211_key_disable_hw_accel(old);
  
  			if (new)
  				ret = ieee80211_key_enable_hw_accel(new);
  		}
62872a9b9   Alexander Wetzel   mac80211: Fix PTK...
395
  	} else {
40b5a0f8c   Gustavo A. R. Silva   mac80211: remove ...
396
  		/* new must be provided in case old is not */
2475b1cc0   Max Stepanov   mac80211: add gen...
397
  		idx = new->conf.keyidx;
40b5a0f8c   Gustavo A. R. Silva   mac80211: remove ...
398
  		if (!new->local->wowlan)
62872a9b9   Alexander Wetzel   mac80211: Fix PTK...
399
  			ret = ieee80211_key_enable_hw_accel(new);
62872a9b9   Alexander Wetzel   mac80211: Fix PTK...
400
401
402
403
  	}
  
  	if (ret)
  		return ret;
3b96766f0   Johannes Berg   mac80211: fix key...
404

2475b1cc0   Max Stepanov   mac80211: add gen...
405
406
407
  	if (sta) {
  		if (pairwise) {
  			rcu_assign_pointer(sta->ptk[idx], new);
96fc6efb9   Alexander Wetzel   mac80211: IEEE 80...
408
409
410
  			if (new &&
  			    !(new->conf.flags & IEEE80211_KEY_FLAG_NO_AUTO_TX)) {
  				sta->ptk_idx = idx;
62872a9b9   Alexander Wetzel   mac80211: Fix PTK...
411
412
413
  				clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
  				ieee80211_check_fast_xmit(sta);
  			}
2475b1cc0   Max Stepanov   mac80211: add gen...
414
415
  		} else {
  			rcu_assign_pointer(sta->gtk[idx], new);
2475b1cc0   Max Stepanov   mac80211: add gen...
416
  		}
96fc6efb9   Alexander Wetzel   mac80211: IEEE 80...
417
418
419
420
421
  		/* Only needed for transition from no key -> key.
  		 * Still triggers unnecessary when using Extended Key ID
  		 * and installing the second key ID the first time.
  		 */
  		if (new && !old)
62872a9b9   Alexander Wetzel   mac80211: Fix PTK...
422
  			ieee80211_check_fast_rx(sta);
2475b1cc0   Max Stepanov   mac80211: add gen...
423
  	} else {
40b275b69   Johannes Berg   mac80211: sparse ...
424
425
426
427
428
429
430
431
432
  		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...
433

f7e0104c1   Johannes Berg   mac80211: support...
434
435
436
437
  		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...
438
439
  		if (defmgmtkey && !new)
  			__ieee80211_set_default_mgmt_key(sdata, -1);
3b96766f0   Johannes Berg   mac80211: fix key...
440
441
  
  		rcu_assign_pointer(sdata->keys[idx], new);
f7e0104c1   Johannes Berg   mac80211: support...
442
443
444
445
446
447
  		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...
448
449
450
  		if (defmgmtkey && new)
  			__ieee80211_set_default_mgmt_key(sdata,
  							 new->conf.keyidx);
3b96766f0   Johannes Berg   mac80211: fix key...
451
  	}
b5c34f662   Johannes Berg   mac80211: fix som...
452
  	if (old)
ef044763a   Eliad Peller   mac80211: add ato...
453
  		list_del_rcu(&old->list);
62872a9b9   Alexander Wetzel   mac80211: Fix PTK...
454
455
  
  	return 0;
11a843b7e   Johannes Berg   [MAC80211]: rewor...
456
  }
2475b1cc0   Max Stepanov   mac80211: add gen...
457
458
459
460
461
  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...
462
463
  {
  	struct ieee80211_key *key;
1ac62ba7c   Ben Hutchings   mac80211: Don't s...
464
  	int i, j, err;
1f5a7e47a   Johannes Berg   [MAC80211]: split...
465

8c5bb1fad   Johannes Berg   mac80211: remove ...
466
467
  	if (WARN_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS))
  		return ERR_PTR(-EINVAL);
11a843b7e   Johannes Berg   [MAC80211]: rewor...
468
469
  
  	key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL);
1f5a7e47a   Johannes Berg   [MAC80211]: split...
470
  	if (!key)
1ac62ba7c   Ben Hutchings   mac80211: Don't s...
471
  		return ERR_PTR(-ENOMEM);
11a843b7e   Johannes Berg   [MAC80211]: rewor...
472
473
474
475
476
  
  	/*
  	 * Default to software encryption; we'll later upload the
  	 * key to the hardware if possible.
  	 */
11a843b7e   Johannes Berg   [MAC80211]: rewor...
477
478
  	key->conf.flags = 0;
  	key->flags = 0;
97359d123   Johannes Berg   mac80211: use cip...
479
  	key->conf.cipher = cipher;
11a843b7e   Johannes Berg   [MAC80211]: rewor...
480
481
  	key->conf.keyidx = idx;
  	key->conf.keylen = key_len;
97359d123   Johannes Berg   mac80211: use cip...
482
483
484
  	switch (cipher) {
  	case WLAN_CIPHER_SUITE_WEP40:
  	case WLAN_CIPHER_SUITE_WEP104:
4325f6caa   Johannes Berg   wireless: move cr...
485
486
  		key->conf.iv_len = IEEE80211_WEP_IV_LEN;
  		key->conf.icv_len = IEEE80211_WEP_ICV_LEN;
76708dee3   Felix Fietkau   mac80211: free up...
487
  		break;
97359d123   Johannes Berg   mac80211: use cip...
488
  	case WLAN_CIPHER_SUITE_TKIP:
4325f6caa   Johannes Berg   wireless: move cr...
489
490
  		key->conf.iv_len = IEEE80211_TKIP_IV_LEN;
  		key->conf.icv_len = IEEE80211_TKIP_ICV_LEN;
9f26a9522   Jouni Malinen   nl80211: Validate...
491
  		if (seq) {
5a306f588   Johannes Berg   mac80211: introdu...
492
  			for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
faa8fdc85   Jouni Malinen   nl80211: Add RSC ...
493
494
495
496
497
498
  				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...
499
  		spin_lock_init(&key->u.tkip.txlock);
76708dee3   Felix Fietkau   mac80211: free up...
500
  		break;
97359d123   Johannes Berg   mac80211: use cip...
501
  	case WLAN_CIPHER_SUITE_CCMP:
4325f6caa   Johannes Berg   wireless: move cr...
502
503
  		key->conf.iv_len = IEEE80211_CCMP_HDR_LEN;
  		key->conf.icv_len = IEEE80211_CCMP_MIC_LEN;
9f26a9522   Jouni Malinen   nl80211: Validate...
504
  		if (seq) {
5a306f588   Johannes Berg   mac80211: introdu...
505
  			for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++)
4325f6caa   Johannes Berg   wireless: move cr...
506
  				for (j = 0; j < IEEE80211_CCMP_PN_LEN; j++)
faa8fdc85   Jouni Malinen   nl80211: Add RSC ...
507
  					key->u.ccmp.rx_pn[i][j] =
4325f6caa   Johannes Berg   wireless: move cr...
508
  						seq[IEEE80211_CCMP_PN_LEN - j - 1];
faa8fdc85   Jouni Malinen   nl80211: Add RSC ...
509
  		}
11a843b7e   Johannes Berg   [MAC80211]: rewor...
510
511
512
513
  		/*
  		 * 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...
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
  		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...
534
535
  		if (IS_ERR(key->u.ccmp.tfm)) {
  			err = PTR_ERR(key->u.ccmp.tfm);
3b96766f0   Johannes Berg   mac80211: fix key...
536
  			kfree(key);
1f951a7f8   Petr Å tetiar   mac80211: fix NUL...
537
  			return ERR_PTR(err);
11a843b7e   Johannes Berg   [MAC80211]: rewor...
538
  		}
60ae0f200   Johannes Berg   mac80211: move ke...
539
540
  		break;
  	case WLAN_CIPHER_SUITE_AES_CMAC:
56c52da2d   Jouni Malinen   mac80111: Add BIP...
541
  	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
60ae0f200   Johannes Berg   mac80211: move ke...
542
  		key->conf.iv_len = 0;
56c52da2d   Jouni Malinen   mac80111: Add BIP...
543
544
545
546
  		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...
547
  		if (seq)
4325f6caa   Johannes Berg   wireless: move cr...
548
  			for (j = 0; j < IEEE80211_CMAC_PN_LEN; j++)
0f9273234   Johannes Berg   mac80211: use CMA...
549
  				key->u.aes_cmac.rx_pn[j] =
4325f6caa   Johannes Berg   wireless: move cr...
550
  					seq[IEEE80211_CMAC_PN_LEN - j - 1];
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
551
552
553
554
555
  		/*
  		 * 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...
556
  			ieee80211_aes_cmac_key_setup(key_data, key_len);
1ac62ba7c   Ben Hutchings   mac80211: Don't s...
557
558
  		if (IS_ERR(key->u.aes_cmac.tfm)) {
  			err = PTR_ERR(key->u.aes_cmac.tfm);
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
559
  			kfree(key);
1f951a7f8   Petr Å tetiar   mac80211: fix NUL...
560
  			return ERR_PTR(err);
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
561
  		}
60ae0f200   Johannes Berg   mac80211: move ke...
562
  		break;
8ade538bf   Jouni Malinen   mac80111: Add BIP...
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
  	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...
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
  	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...
601
602
  	default:
  		if (cs) {
e3a55b539   Johannes Berg   mac80211: validat...
603
604
605
606
  			if (seq_len && seq_len != cs->pn_len) {
  				kfree(key);
  				return ERR_PTR(-EINVAL);
  			}
2475b1cc0   Max Stepanov   mac80211: add gen...
607
608
609
610
  
  			key->conf.iv_len = cs->hdr_len;
  			key->conf.icv_len = cs->mic_len;
  			for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++)
e3a55b539   Johannes Berg   mac80211: validat...
611
  				for (j = 0; j < seq_len; j++)
2475b1cc0   Max Stepanov   mac80211: add gen...
612
  					key->u.gen.rx_pn[i][j] =
e3a55b539   Johannes Berg   mac80211: validat...
613
  							seq[seq_len - j - 1];
c7ef38e0c   Cedric Izoard   mac80211: Get IV ...
614
  			key->flags |= KEY_FLAG_CIPHER_SCHEME;
2475b1cc0   Max Stepanov   mac80211: add gen...
615
  		}
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
616
  	}
60ae0f200   Johannes Berg   mac80211: move ke...
617
618
  	memcpy(key->conf.key, key_data, key_len);
  	INIT_LIST_HEAD(&key->list);
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
619

db4d1169d   Johannes Berg   mac80211: split i...
620
621
  	return key;
  }
11a843b7e   Johannes Berg   [MAC80211]: rewor...
622

79cf2dfa3   Johannes Berg   mac80211: clean u...
623
624
  static void ieee80211_key_free_common(struct ieee80211_key *key)
  {
00b9cfa3f   Jouni Malinen   mac80111: Add GCM...
625
626
  	switch (key->conf.cipher) {
  	case WLAN_CIPHER_SUITE_CCMP:
2b2ba0db1   Jouni Malinen   mac80111: Add CCM...
627
  	case WLAN_CIPHER_SUITE_CCMP_256:
79cf2dfa3   Johannes Berg   mac80211: clean u...
628
  		ieee80211_aes_key_free(key->u.ccmp.tfm);
00b9cfa3f   Jouni Malinen   mac80111: Add GCM...
629
630
  		break;
  	case WLAN_CIPHER_SUITE_AES_CMAC:
56c52da2d   Jouni Malinen   mac80111: Add BIP...
631
  	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
79cf2dfa3   Johannes Berg   mac80211: clean u...
632
  		ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
00b9cfa3f   Jouni Malinen   mac80111: Add GCM...
633
  		break;
8ade538bf   Jouni Malinen   mac80111: Add BIP...
634
635
636
637
  	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...
638
639
640
641
642
  	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...
643
  	kzfree(key);
79cf2dfa3   Johannes Berg   mac80211: clean u...
644
  }
6d10e46be   Johannes Berg   mac80211: batch k...
645
646
  static void __ieee80211_key_destroy(struct ieee80211_key *key,
  				    bool delay_tailroom)
ad0e2b5a0   Johannes Berg   mac80211: simplif...
647
  {
3bff18651   Yogesh Ashok Powar   mac80211: Skip ta...
648
  	if (key->local) {
8d1f7ecd2   Johannes Berg   mac80211: defer t...
649
  		struct ieee80211_sub_if_data *sdata = key->sdata;
32162a4da   Jouni Malinen   mac80211: Fix key...
650
  		ieee80211_debugfs_key_remove(key);
8d1f7ecd2   Johannes Berg   mac80211: defer t...
651
652
653
654
655
656
657
  
  		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 {
f9dca80b9   Michal Kazior   mac80211: fix AP_...
658
  			decrease_tailroom_need_count(sdata, 1);
8d1f7ecd2   Johannes Berg   mac80211: defer t...
659
  		}
3bff18651   Yogesh Ashok Powar   mac80211: Skip ta...
660
  	}
ad0e2b5a0   Johannes Berg   mac80211: simplif...
661

79cf2dfa3   Johannes Berg   mac80211: clean u...
662
663
  	ieee80211_key_free_common(key);
  }
6d10e46be   Johannes Berg   mac80211: batch k...
664
665
666
667
668
669
670
  static void ieee80211_key_destroy(struct ieee80211_key *key,
  				  bool delay_tailroom)
  {
  	if (!key)
  		return;
  
  	/*
ef044763a   Eliad Peller   mac80211: add ato...
671
672
  	 * Synchronize so the TX path and rcu key iterators
  	 * can no longer be using this key before we free/remove it.
6d10e46be   Johannes Berg   mac80211: batch k...
673
674
675
676
677
  	 */
  	synchronize_net();
  
  	__ieee80211_key_destroy(key, delay_tailroom);
  }
79cf2dfa3   Johannes Berg   mac80211: clean u...
678
679
680
681
  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...
682
  }
cfbb0d90a   Johannes Berg   mac80211: don't c...
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
  static bool ieee80211_key_identical(struct ieee80211_sub_if_data *sdata,
  				    struct ieee80211_key *old,
  				    struct ieee80211_key *new)
  {
  	u8 tkip_old[WLAN_KEY_LEN_TKIP], tkip_new[WLAN_KEY_LEN_TKIP];
  	u8 *tk_old, *tk_new;
  
  	if (!old || new->conf.keylen != old->conf.keylen)
  		return false;
  
  	tk_old = old->conf.key;
  	tk_new = new->conf.key;
  
  	/*
  	 * In station mode, don't compare the TX MIC key, as it's never used
  	 * and offloaded rekeying may not care to send it to the host. This
  	 * is the case in iwlwifi, for example.
  	 */
  	if (sdata->vif.type == NL80211_IFTYPE_STATION &&
  	    new->conf.cipher == WLAN_CIPHER_SUITE_TKIP &&
  	    new->conf.keylen == WLAN_KEY_LEN_TKIP &&
  	    !(new->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
  		memcpy(tkip_old, tk_old, WLAN_KEY_LEN_TKIP);
  		memcpy(tkip_new, tk_new, WLAN_KEY_LEN_TKIP);
  		memset(tkip_old + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, 0, 8);
  		memset(tkip_new + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, 0, 8);
  		tk_old = tkip_old;
  		tk_new = tkip_new;
  	}
  
  	return !crypto_memneq(tk_old, tk_new, new->conf.keylen);
  }
3ffc2a905   Johannes Berg   mac80211: allow v...
715
716
717
  int ieee80211_key_link(struct ieee80211_key *key,
  		       struct ieee80211_sub_if_data *sdata,
  		       struct sta_info *sta)
db4d1169d   Johannes Berg   mac80211: split i...
718
719
  {
  	struct ieee80211_key *old_key;
133bf90db   Manikanta Pubbisetty   mac80211: restric...
720
721
722
723
724
725
726
727
  	int idx = key->conf.keyidx;
  	bool pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE;
  	/*
  	 * We want to delay tailroom updates only for station - in that
  	 * case it helps roaming speed, but in other cases it hurts and
  	 * can cause warnings to appear.
  	 */
  	bool delay_tailroom = sdata->vif.type == NL80211_IFTYPE_STATION;
96fc6efb9   Alexander Wetzel   mac80211: IEEE 80...
728
  	int ret = -EOPNOTSUPP;
db4d1169d   Johannes Berg   mac80211: split i...
729

ad0e2b5a0   Johannes Berg   mac80211: simplif...
730
  	mutex_lock(&sdata->local->key_mtx);
3b96766f0   Johannes Berg   mac80211: fix key...
731

96fc6efb9   Alexander Wetzel   mac80211: IEEE 80...
732
733
  	if (sta && pairwise) {
  		struct ieee80211_key *alt_key;
2475b1cc0   Max Stepanov   mac80211: add gen...
734
  		old_key = key_mtx_dereference(sdata->local, sta->ptk[idx]);
96fc6efb9   Alexander Wetzel   mac80211: IEEE 80...
735
736
737
738
739
  		alt_key = key_mtx_dereference(sdata->local, sta->ptk[idx ^ 1]);
  
  		/* The rekey code assumes that the old and new key are using
  		 * the same cipher. Enforce the assumption for pairwise keys.
  		 */
1c9559734   Johannes Berg   mac80211: remove ...
740
741
  		if ((alt_key && alt_key->conf.cipher != key->conf.cipher) ||
  		    (old_key && old_key->conf.cipher != key->conf.cipher))
96fc6efb9   Alexander Wetzel   mac80211: IEEE 80...
742
743
  			goto out;
  	} else if (sta) {
40b275b69   Johannes Berg   mac80211: sparse ...
744
  		old_key = key_mtx_dereference(sdata->local, sta->gtk[idx]);
96fc6efb9   Alexander Wetzel   mac80211: IEEE 80...
745
  	} else {
40b275b69   Johannes Berg   mac80211: sparse ...
746
  		old_key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
96fc6efb9   Alexander Wetzel   mac80211: IEEE 80...
747
748
749
750
  	}
  
  	/* Non-pairwise keys must also not switch the cipher on rekey */
  	if (!pairwise) {
753a9a729   Luca Coelho   mac80211: don't c...
751
  		if (old_key && old_key->conf.cipher != key->conf.cipher)
96fc6efb9   Alexander Wetzel   mac80211: IEEE 80...
752
753
  			goto out;
  	}
db4d1169d   Johannes Berg   mac80211: split i...
754

fdf7cb418   Johannes Berg   mac80211: accept ...
755
756
757
758
  	/*
  	 * Silently accept key re-installation without really installing the
  	 * new version of the key to avoid nonce reuse or replay issues.
  	 */
cfbb0d90a   Johannes Berg   mac80211: don't c...
759
  	if (ieee80211_key_identical(sdata, old_key, key)) {
fdf7cb418   Johannes Berg   mac80211: accept ...
760
761
762
763
764
765
766
767
  		ieee80211_key_free_unused(key);
  		ret = 0;
  		goto out;
  	}
  
  	key->local = sdata->local;
  	key->sdata = sdata;
  	key->sta = sta;
3bff18651   Yogesh Ashok Powar   mac80211: Skip ta...
768
  	increment_tailroom_need_count(sdata);
62872a9b9   Alexander Wetzel   mac80211: Fix PTK...
769
  	ret = ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
db4d1169d   Johannes Berg   mac80211: split i...
770

62872a9b9   Alexander Wetzel   mac80211: Fix PTK...
771
772
773
  	if (!ret) {
  		ieee80211_debugfs_key_add(key);
  		ieee80211_key_destroy(old_key, delay_tailroom);
27b3eb9c0   Johannes Berg   mac80211: add API...
774
  	} else {
62872a9b9   Alexander Wetzel   mac80211: Fix PTK...
775
  		ieee80211_key_free(key, delay_tailroom);
27b3eb9c0   Johannes Berg   mac80211: add API...
776
  	}
79cf2dfa3   Johannes Berg   mac80211: clean u...
777

fdf7cb418   Johannes Berg   mac80211: accept ...
778
   out:
ad0e2b5a0   Johannes Berg   mac80211: simplif...
779
  	mutex_unlock(&sdata->local->key_mtx);
3ffc2a905   Johannes Berg   mac80211: allow v...
780
781
  
  	return ret;
1f5a7e47a   Johannes Berg   [MAC80211]: split...
782
  }
3b8d9c290   Johannes Berg   mac80211: remove ...
783
  void ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom)
1f5a7e47a   Johannes Berg   [MAC80211]: split...
784
  {
5c0c36412   Johannes Berg   mac80211: make ke...
785
786
  	if (!key)
  		return;
3b96766f0   Johannes Berg   mac80211: fix key...
787
788
789
  	/*
  	 * Replace key with nothingness if it was ever used.
  	 */
3a2457669   Johannes Berg   mac80211: fix key...
790
  	if (key->sdata)
3b8d9c290   Johannes Berg   mac80211: remove ...
791
  		ieee80211_key_replace(key->sdata, key->sta,
e31b82136   Johannes Berg   cfg80211/mac80211...
792
793
  				key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
  				key, NULL);
3b8d9c290   Johannes Berg   mac80211: remove ...
794
  	ieee80211_key_destroy(key, delay_tailroom);
3b96766f0   Johannes Berg   mac80211: fix key...
795
  }
d4e46a3d9   Johannes Berg   [MAC80211]: fix r...
796

624ff4b21   Lior Cohen   mac80211: clear c...
797
  void ieee80211_reenable_keys(struct ieee80211_sub_if_data *sdata)
3a2457669   Johannes Berg   mac80211: fix key...
798
799
  {
  	struct ieee80211_key *key;
f9dca80b9   Michal Kazior   mac80211: fix AP_...
800
  	struct ieee80211_sub_if_data *vlan;
11a843b7e   Johannes Berg   [MAC80211]: rewor...
801

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

f9dca80b9   Michal Kazior   mac80211: fix AP_...
804
805
806
  	mutex_lock(&sdata->local->key_mtx);
  
  	sdata->crypto_tx_tailroom_needed_cnt = 0;
624ff4b21   Lior Cohen   mac80211: clear c...
807
  	sdata->crypto_tx_tailroom_pending_dec = 0;
f9dca80b9   Michal Kazior   mac80211: fix AP_...
808
809
  
  	if (sdata->vif.type == NL80211_IFTYPE_AP) {
624ff4b21   Lior Cohen   mac80211: clear c...
810
  		list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
f9dca80b9   Michal Kazior   mac80211: fix AP_...
811
  			vlan->crypto_tx_tailroom_needed_cnt = 0;
624ff4b21   Lior Cohen   mac80211: clear c...
812
813
814
815
816
817
818
819
820
  			vlan->crypto_tx_tailroom_pending_dec = 0;
  		}
  	}
  
  	if (ieee80211_sdata_running(sdata)) {
  		list_for_each_entry(key, &sdata->key_list, list) {
  			increment_tailroom_need_count(sdata);
  			ieee80211_key_enable_hw_accel(key);
  		}
f9dca80b9   Michal Kazior   mac80211: fix AP_...
821
822
823
824
  	}
  
  	mutex_unlock(&sdata->local->key_mtx);
  }
830af02f2   Johannes Berg   mac80211: allow d...
825
826
827
828
829
830
831
832
833
834
  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...
835
  	struct ieee80211_key *key, *tmp;
830af02f2   Johannes Berg   mac80211: allow d...
836
837
838
839
840
841
842
  	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...
843
  		list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
830af02f2   Johannes Berg   mac80211: allow d...
844
845
846
847
848
  			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...
849
850
  			list_for_each_entry_safe(key, tmp,
  						 &sdata->key_list, list)
830af02f2   Johannes Berg   mac80211: allow d...
851
852
853
854
855
856
857
  				iter(hw, &sdata->vif,
  				     key->sta ? &key->sta->sta : NULL,
  				     &key->conf, iter_data);
  	}
  	mutex_unlock(&local->key_mtx);
  }
  EXPORT_SYMBOL(ieee80211_iter_keys);
ef044763a   Eliad Peller   mac80211: add ato...
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
  static void
  _ieee80211_iter_keys_rcu(struct ieee80211_hw *hw,
  			 struct ieee80211_sub_if_data *sdata,
  			 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_key *key;
  
  	list_for_each_entry_rcu(key, &sdata->key_list, list) {
  		/* skip keys of station in removal process */
  		if (key->sta && key->sta->removed)
  			continue;
  		if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
  			continue;
  
  		iter(hw, &sdata->vif,
  		     key->sta ? &key->sta->sta : NULL,
  		     &key->conf, iter_data);
  	}
  }
  
  void ieee80211_iter_keys_rcu(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);
  	struct ieee80211_sub_if_data *sdata;
  
  	if (vif) {
  		sdata = vif_to_sdata(vif);
  		_ieee80211_iter_keys_rcu(hw, sdata, iter, iter_data);
  	} else {
  		list_for_each_entry_rcu(sdata, &local->interfaces, list)
  			_ieee80211_iter_keys_rcu(hw, sdata, iter, iter_data);
  	}
  }
  EXPORT_SYMBOL(ieee80211_iter_keys_rcu);
7907c7d33   Johannes Berg   mac80211: free al...
904
905
  static void ieee80211_free_keys_iface(struct ieee80211_sub_if_data *sdata,
  				      struct list_head *keys)
3b96766f0   Johannes Berg   mac80211: fix key...
906
907
  {
  	struct ieee80211_key *key, *tmp;
3b96766f0   Johannes Berg   mac80211: fix key...
908

f9dca80b9   Michal Kazior   mac80211: fix AP_...
909
910
  	decrease_tailroom_need_count(sdata,
  				     sdata->crypto_tx_tailroom_pending_dec);
8d1f7ecd2   Johannes Berg   mac80211: defer t...
911
  	sdata->crypto_tx_tailroom_pending_dec = 0;
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
912
  	ieee80211_debugfs_key_remove_mgmt_default(sdata);
3b96766f0   Johannes Berg   mac80211: fix key...
913

6d10e46be   Johannes Berg   mac80211: batch k...
914
915
916
917
  	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...
918
  		list_add_tail(&key->list, keys);
6d10e46be   Johannes Berg   mac80211: batch k...
919
  	}
3b96766f0   Johannes Berg   mac80211: fix key...
920

f7e0104c1   Johannes Berg   mac80211: support...
921
  	ieee80211_debugfs_key_update_default(sdata);
7907c7d33   Johannes Berg   mac80211: free al...
922
  }
f7e0104c1   Johannes Berg   mac80211: support...
923

7907c7d33   Johannes Berg   mac80211: free al...
924
925
926
927
928
  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;
f9dca80b9   Michal Kazior   mac80211: fix AP_...
929
  	struct ieee80211_sub_if_data *master;
7907c7d33   Johannes Berg   mac80211: free al...
930
931
932
933
934
935
936
937
938
939
940
941
  	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...
942
  	}
7907c7d33   Johannes Berg   mac80211: free al...
943
944
945
946
  	if (!list_empty(&keys) || force_synchronize)
  		synchronize_net();
  	list_for_each_entry_safe(key, tmp, &keys, list)
  		__ieee80211_key_destroy(key, false);
f9dca80b9   Michal Kazior   mac80211: fix AP_...
947
948
949
950
951
952
953
954
955
956
957
958
959
  	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
  		if (sdata->bss) {
  			master = container_of(sdata->bss,
  					      struct ieee80211_sub_if_data,
  					      u.ap);
  
  			WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt !=
  				     master->crypto_tx_tailroom_needed_cnt);
  		}
  	} else {
  		WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt ||
  			     sdata->crypto_tx_tailroom_pending_dec);
  	}
7907c7d33   Johannes Berg   mac80211: free al...
960
961
962
963
964
  	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...
965

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

6d10e46be   Johannes Berg   mac80211: batch k...
969
970
971
  void ieee80211_free_sta_keys(struct ieee80211_local *local,
  			     struct sta_info *sta)
  {
c87820784   Johannes Berg   mac80211: move sy...
972
  	struct ieee80211_key *key;
6d10e46be   Johannes Berg   mac80211: batch k...
973
974
975
  	int i;
  
  	mutex_lock(&local->key_mtx);
28a9bc681   Johannes Berg   mac80211: free ma...
976
  	for (i = 0; i < ARRAY_SIZE(sta->gtk); i++) {
6d10e46be   Johannes Berg   mac80211: batch k...
977
978
979
980
981
982
  		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);
133bf90db   Manikanta Pubbisetty   mac80211: restric...
983
984
  		__ieee80211_key_destroy(key, key->sdata->vif.type ==
  					NL80211_IFTYPE_STATION);
6d10e46be   Johannes Berg   mac80211: batch k...
985
  	}
2475b1cc0   Max Stepanov   mac80211: add gen...
986
987
988
989
  	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...
990
991
992
  		ieee80211_key_replace(key->sdata, key->sta,
  				key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
  				key, NULL);
133bf90db   Manikanta Pubbisetty   mac80211: restric...
993
994
  		__ieee80211_key_destroy(key, key->sdata->vif.type ==
  					NL80211_IFTYPE_STATION);
c87820784   Johannes Berg   mac80211: move sy...
995
  	}
6d10e46be   Johannes Berg   mac80211: batch k...
996
997
998
  
  	mutex_unlock(&local->key_mtx);
  }
8d1f7ecd2   Johannes Berg   mac80211: defer t...
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
  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);
f9dca80b9   Michal Kazior   mac80211: fix AP_...
1023
1024
  	decrease_tailroom_need_count(sdata,
  				     sdata->crypto_tx_tailroom_pending_dec);
8d1f7ecd2   Johannes Berg   mac80211: defer t...
1025
1026
1027
  	sdata->crypto_tx_tailroom_pending_dec = 0;
  	mutex_unlock(&sdata->local->key_mtx);
  }
c68f4b892   Johannes Berg   mac80211: support...
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
  
  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...
1039

3ea542d3c   Johannes Berg   mac80211: allow d...
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
  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...
1050
  		if (WARN_ON(tid < 0 || tid >= IEEE80211_NUM_TIDS))
3ea542d3c   Johannes Berg   mac80211: allow d...
1051
1052
1053
1054
1055
  			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...
1056
  	case WLAN_CIPHER_SUITE_CCMP_256:
5a306f588   Johannes Berg   mac80211: introdu...
1057
  		if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS))
3ea542d3c   Johannes Berg   mac80211: allow d...
1058
1059
  			return;
  		if (tid < 0)
5a306f588   Johannes Berg   mac80211: introdu...
1060
  			pn = key->u.ccmp.rx_pn[IEEE80211_NUM_TIDS];
3ea542d3c   Johannes Berg   mac80211: allow d...
1061
1062
  		else
  			pn = key->u.ccmp.rx_pn[tid];
4325f6caa   Johannes Berg   wireless: move cr...
1063
  		memcpy(seq->ccmp.pn, pn, IEEE80211_CCMP_PN_LEN);
3ea542d3c   Johannes Berg   mac80211: allow d...
1064
1065
  		break;
  	case WLAN_CIPHER_SUITE_AES_CMAC:
56c52da2d   Jouni Malinen   mac80111: Add BIP...
1066
  	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
3ea542d3c   Johannes Berg   mac80211: allow d...
1067
1068
1069
  		if (WARN_ON(tid != 0))
  			return;
  		pn = key->u.aes_cmac.rx_pn;
4325f6caa   Johannes Berg   wireless: move cr...
1070
  		memcpy(seq->aes_cmac.pn, pn, IEEE80211_CMAC_PN_LEN);
3ea542d3c   Johannes Berg   mac80211: allow d...
1071
  		break;
8ade538bf   Jouni Malinen   mac80111: Add BIP...
1072
1073
1074
1075
1076
1077
1078
  	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...
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
  	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...
1089
1090
1091
  	}
  }
  EXPORT_SYMBOL(ieee80211_get_key_rx_seq);
27b3eb9c0   Johannes Berg   mac80211: add API...
1092

27b3eb9c0   Johannes Berg   mac80211: add API...
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
  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...
1109
  	case WLAN_CIPHER_SUITE_CCMP_256:
27b3eb9c0   Johannes Berg   mac80211: add API...
1110
1111
1112
1113
1114
1115
1116
1117
1118
  		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...
1119
  	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
27b3eb9c0   Johannes Berg   mac80211: add API...
1120
1121
1122
1123
1124
  		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...
1125
1126
1127
1128
1129
1130
1131
  	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...
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
  	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...
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
  	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;
092c4098f   Alexander Wetzel   mac80211: Optimiz...
1163
1164
1165
  		if (!(key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
  					 IEEE80211_KEY_FLAG_PUT_MIC_SPACE |
  					 IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
27b3eb9c0   Johannes Berg   mac80211: add API...
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
  			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...
1190
  				  0, NULL, NULL);
27b3eb9c0   Johannes Berg   mac80211: add API...
1191
  	if (IS_ERR(key))
c5dc164df   Johannes Berg   mac80211: use ERR...
1192
  		return ERR_CAST(key);
27b3eb9c0   Johannes Berg   mac80211: add API...
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
  
  	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);