key.c 18.0 KB
Newer Older
1 2 3 4
/*
 * Copyright 2002-2005, Instant802 Networks, Inc.
 * Copyright 2005-2006, Devicescape Software, Inc.
 * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
5
 * Copyright 2007-2008	Johannes Berg <johannes@sipsolutions.net>
6 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.
 */

J
Johannes Berg 已提交
12 13 14
#include <linux/if_ether.h>
#include <linux/etherdevice.h>
#include <linux/list.h>
15
#include <linux/rcupdate.h>
16
#include <linux/rtnetlink.h>
17
#include <linux/slab.h>
18 19
#include <net/mac80211.h>
#include "ieee80211_i.h"
20
#include "driver-ops.h"
21 22
#include "debugfs_key.h"
#include "aes_ccm.h"
23
#include "aes_cmac.h"
24

J
Johannes Berg 已提交
25

J
Johannes Berg 已提交
26 27
/**
 * DOC: Key handling basics
J
Johannes Berg 已提交
28 29 30 31 32
 *
 * 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.
 *
33 34 35 36 37 38 39
 * 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.
J
Johannes Berg 已提交
40
 *
41 42 43 44 45 46
 * 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.
J
Johannes Berg 已提交
47 48 49 50
 */

static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };

J
Johannes Berg 已提交
51
static void assert_key_lock(struct ieee80211_local *local)
52
{
53
	lockdep_assert_held(&local->key_mtx);
54 55
}

56
static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key)
J
Johannes Berg 已提交
57 58
{
	if (key->sta)
59
		return &key->sta->sta;
J
Johannes Berg 已提交
60

61
	return NULL;
J
Johannes Berg 已提交
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 88 89 90 91 92 93
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();
	}
}

94
static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
J
Johannes Berg 已提交
95
{
96 97
	struct ieee80211_sub_if_data *sdata;
	struct ieee80211_sta *sta;
J
Johannes Berg 已提交
98 99
	int ret;

100 101
	might_sleep();

102
	if (!key->local->ops->set_key)
103
		goto out_unsupported;
J
Johannes Berg 已提交
104

J
Johannes Berg 已提交
105 106
	assert_key_lock(key->local);

107 108
	sta = get_sta_for_key(key);

109 110 111 112 113 114 115 116
	/*
	 * 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;

117
	sdata = key->sdata;
118 119 120 121 122 123 124
	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;
125 126 127
		sdata = container_of(sdata->bss,
				     struct ieee80211_sub_if_data,
				     u.ap);
128
	}
J
Johannes Berg 已提交
129

J
Johannes Berg 已提交
130
	ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf);
J
Johannes Berg 已提交
131

132
	if (!ret) {
J
Johannes Berg 已提交
133
		key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
134 135 136 137 138

		if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
		      (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)))
			sdata->crypto_tx_tailroom_needed_cnt--;

139 140
		return 0;
	}
J
Johannes Berg 已提交
141

142
	if (ret != -ENOSPC && ret != -EOPNOTSUPP)
J
Joe Perches 已提交
143 144 145
		wiphy_err(key->local->hw.wiphy,
			  "failed to set key (%d, %pM) to hardware (%d)\n",
			  key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
146

147 148 149 150 151 152 153 154 155 156 157
 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:
	case WLAN_CIPHER_SUITE_AES_CMAC:
		/* all of these we can do in software */
		return 0;
	default:
		return -EINVAL;
158
	}
J
Johannes Berg 已提交
159 160 161 162
}

static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
{
163 164
	struct ieee80211_sub_if_data *sdata;
	struct ieee80211_sta *sta;
J
Johannes Berg 已提交
165 166
	int ret;

167 168
	might_sleep();

169
	if (!key || !key->local->ops->set_key)
J
Johannes Berg 已提交
170 171
		return;

J
Johannes Berg 已提交
172 173 174
	assert_key_lock(key->local);

	if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
J
Johannes Berg 已提交
175 176
		return;

177 178 179
	sta = get_sta_for_key(key);
	sdata = key->sdata;

180 181 182 183
	if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
	      (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)))
		increment_tailroom_need_count(sdata);

184 185 186 187
	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
		sdata = container_of(sdata->bss,
				     struct ieee80211_sub_if_data,
				     u.ap);
J
Johannes Berg 已提交
188

J
Johannes Berg 已提交
189
	ret = drv_set_key(key->local, DISABLE_KEY, sdata,
190
			  sta, &key->conf);
J
Johannes Berg 已提交
191 192

	if (ret)
J
Joe Perches 已提交
193 194 195
		wiphy_err(key->local->hw.wiphy,
			  "failed to remove key (%d, %pM) from hardware (%d)\n",
			  key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
J
Johannes Berg 已提交
196

197 198 199
	key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
}

200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
void ieee80211_key_removed(struct ieee80211_key_conf *key_conf)
{
	struct ieee80211_key *key;

	key = container_of(key_conf, struct ieee80211_key, conf);

	might_sleep();
	assert_key_lock(key->local);

	key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;

	/*
	 * Flush TX path to avoid attempts to use this key
	 * after this function returns. Until then, drivers
	 * must be prepared to handle the key.
	 */
	synchronize_rcu();
}
EXPORT_SYMBOL_GPL(ieee80211_key_removed);

220
static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
221
					int idx, bool uni, bool multi)
222 223 224
{
	struct ieee80211_key *key = NULL;

J
Johannes Berg 已提交
225 226
	assert_key_lock(sdata->local);

227
	if (idx >= 0 && idx < NUM_DEFAULT_KEYS)
J
Johannes Berg 已提交
228
		key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
229

230 231 232 233
	if (uni)
		rcu_assign_pointer(sdata->default_unicast_key, key);
	if (multi)
		rcu_assign_pointer(sdata->default_multicast_key, key);
234

235
	ieee80211_debugfs_key_update_default(sdata);
236 237
}

238 239
void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx,
			       bool uni, bool multi)
240
{
J
Johannes Berg 已提交
241
	mutex_lock(&sdata->local->key_mtx);
242
	__ieee80211_set_default_key(sdata, idx, uni, multi);
J
Johannes Berg 已提交
243
	mutex_unlock(&sdata->local->key_mtx);
244 245
}

246 247 248 249 250
static void
__ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx)
{
	struct ieee80211_key *key = NULL;

J
Johannes Berg 已提交
251 252
	assert_key_lock(sdata->local);

253 254
	if (idx >= NUM_DEFAULT_KEYS &&
	    idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
J
Johannes Berg 已提交
255
		key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
256 257 258

	rcu_assign_pointer(sdata->default_mgmt_key, key);

259
	ieee80211_debugfs_key_update_default(sdata);
260 261 262 263 264
}

void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
				    int idx)
{
J
Johannes Berg 已提交
265
	mutex_lock(&sdata->local->key_mtx);
266
	__ieee80211_set_default_mgmt_key(sdata, idx);
J
Johannes Berg 已提交
267
	mutex_unlock(&sdata->local->key_mtx);
268 269
}

270 271 272

static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
				    struct sta_info *sta,
273
				    bool pairwise,
274 275 276
				    struct ieee80211_key *old,
				    struct ieee80211_key *new)
{
277 278
	int idx;
	bool defunikey, defmultikey, defmgmtkey;
279 280

	if (new)
281
		list_add_tail(&new->list, &sdata->key_list);
282

283 284 285 286 287 288 289 290
	if (sta && pairwise) {
		rcu_assign_pointer(sta->ptk, new);
	} else if (sta) {
		if (old)
			idx = old->conf.keyidx;
		else
			idx = new->conf.keyidx;
		rcu_assign_pointer(sta->gtk[idx], new);
291 292 293 294 295 296 297 298
	} else {
		WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx);

		if (old)
			idx = old->conf.keyidx;
		else
			idx = new->conf.keyidx;

J
Johannes Berg 已提交
299 300 301 302 303 304 305 306 307
		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);
308

309 310 311 312
		if (defunikey && !new)
			__ieee80211_set_default_key(sdata, -1, true, false);
		if (defmultikey && !new)
			__ieee80211_set_default_key(sdata, -1, false, true);
313 314
		if (defmgmtkey && !new)
			__ieee80211_set_default_mgmt_key(sdata, -1);
315 316

		rcu_assign_pointer(sdata->keys[idx], new);
317 318 319 320 321 322
		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);
323 324 325
		if (defmgmtkey && new)
			__ieee80211_set_default_mgmt_key(sdata,
							 new->conf.keyidx);
326 327
	}

328 329
	if (old)
		list_del(&old->list);
J
Johannes Berg 已提交
330 331
}

332
struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
333 334
					  const u8 *key_data,
					  size_t seq_len, const u8 *seq)
335 336
{
	struct ieee80211_key *key;
337
	int i, j, err;
338

339
	BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS);
J
Johannes Berg 已提交
340 341

	key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL);
342
	if (!key)
343
		return ERR_PTR(-ENOMEM);
J
Johannes Berg 已提交
344 345 346 347 348 349 350 351

	/*
	 * Default to software encryption; we'll later upload the
	 * key to the hardware if possible.
	 */
	key->conf.flags = 0;
	key->flags = 0;

352
	key->conf.cipher = cipher;
J
Johannes Berg 已提交
353 354
	key->conf.keyidx = idx;
	key->conf.keylen = key_len;
355 356 357
	switch (cipher) {
	case WLAN_CIPHER_SUITE_WEP40:
	case WLAN_CIPHER_SUITE_WEP104:
358 359 360
		key->conf.iv_len = WEP_IV_LEN;
		key->conf.icv_len = WEP_ICV_LEN;
		break;
361
	case WLAN_CIPHER_SUITE_TKIP:
362 363
		key->conf.iv_len = TKIP_IV_LEN;
		key->conf.icv_len = TKIP_ICV_LEN;
364
		if (seq) {
365 366 367 368 369 370 371
			for (i = 0; i < NUM_RX_DATA_QUEUES; i++) {
				key->u.tkip.rx[i].iv32 =
					get_unaligned_le32(&seq[2]);
				key->u.tkip.rx[i].iv16 =
					get_unaligned_le16(seq);
			}
		}
372
		spin_lock_init(&key->u.tkip.txlock);
373
		break;
374
	case WLAN_CIPHER_SUITE_CCMP:
375 376
		key->conf.iv_len = CCMP_HDR_LEN;
		key->conf.icv_len = CCMP_MIC_LEN;
377
		if (seq) {
378
			for (i = 0; i < NUM_RX_DATA_QUEUES + 1; i++)
379 380 381 382
				for (j = 0; j < CCMP_PN_LEN; j++)
					key->u.ccmp.rx_pn[i][j] =
						seq[CCMP_PN_LEN - j - 1];
		}
J
Johannes Berg 已提交
383 384 385 386 387
		/*
		 * 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);
388 389
		if (IS_ERR(key->u.ccmp.tfm)) {
			err = PTR_ERR(key->u.ccmp.tfm);
390
			kfree(key);
391
			return ERR_PTR(err);
J
Johannes Berg 已提交
392
		}
J
Johannes Berg 已提交
393 394 395 396 397 398 399
		break;
	case WLAN_CIPHER_SUITE_AES_CMAC:
		key->conf.iv_len = 0;
		key->conf.icv_len = sizeof(struct ieee80211_mmie);
		if (seq)
			for (j = 0; j < 6; j++)
				key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1];
400 401 402 403 404 405
		/*
		 * 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 =
			ieee80211_aes_cmac_key_setup(key_data);
406 407
		if (IS_ERR(key->u.aes_cmac.tfm)) {
			err = PTR_ERR(key->u.aes_cmac.tfm);
408
			kfree(key);
409
			return ERR_PTR(err);
410
		}
J
Johannes Berg 已提交
411
		break;
412
	}
J
Johannes Berg 已提交
413 414
	memcpy(key->conf.key, key_data, key_len);
	INIT_LIST_HEAD(&key->list);
415

416 417
	return key;
}
J
Johannes Berg 已提交
418

J
Johannes Berg 已提交
419 420 421 422 423
static void __ieee80211_key_destroy(struct ieee80211_key *key)
{
	if (!key)
		return;

424 425 426 427 428 429
	/*
	 * Synchronize so the TX path can no longer be using
	 * this key before we free/remove it.
	 */
	synchronize_rcu();

430 431
	if (key->local)
		ieee80211_key_disable_hw_accel(key);
J
Johannes Berg 已提交
432

433
	if (key->conf.cipher == WLAN_CIPHER_SUITE_CCMP)
J
Johannes Berg 已提交
434
		ieee80211_aes_key_free(key->u.ccmp.tfm);
435
	if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC)
J
Johannes Berg 已提交
436
		ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
437
	if (key->local) {
438
		ieee80211_debugfs_key_remove(key);
439 440
		key->sdata->crypto_tx_tailroom_needed_cnt--;
	}
J
Johannes Berg 已提交
441 442 443 444

	kfree(key);
}

445 446 447
int ieee80211_key_link(struct ieee80211_key *key,
		       struct ieee80211_sub_if_data *sdata,
		       struct sta_info *sta)
448 449
{
	struct ieee80211_key *old_key;
450
	int idx, ret;
451
	bool pairwise;
452 453 454 455

	BUG_ON(!sdata);
	BUG_ON(!key);

456
	pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE;
457 458 459 460 461
	idx = key->conf.keyidx;
	key->local = sdata->local;
	key->sdata = sdata;
	key->sta = sta;

J
Johannes Berg 已提交
462 463 464 465 466
	if (sta) {
		/*
		 * some hardware cannot handle TKIP with QoS, so
		 * we indicate whether QoS could be in use.
		 */
467
		if (test_sta_flags(sta, WLAN_STA_WME))
J
Johannes Berg 已提交
468 469
			key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA;
	} else {
470
		if (sdata->vif.type == NL80211_IFTYPE_STATION) {
J
Johannes Berg 已提交
471 472
			struct sta_info *ap;

473
			/*
474 475
			 * We're getting a sta pointer in, so must be under
			 * appropriate locking for sta_info_get().
476
			 */
477

J
Johannes Berg 已提交
478
			/* same here, the AP could be using QoS */
479
			ap = sta_info_get(key->sdata, key->sdata->u.mgd.bssid);
J
Johannes Berg 已提交
480
			if (ap) {
481
				if (test_sta_flags(ap, WLAN_STA_WME))
J
Johannes Berg 已提交
482 483 484 485 486 487
					key->conf.flags |=
						IEEE80211_KEY_FLAG_WMM_STA;
			}
		}
	}

J
Johannes Berg 已提交
488
	mutex_lock(&sdata->local->key_mtx);
489

490
	if (sta && pairwise)
J
Johannes Berg 已提交
491
		old_key = key_mtx_dereference(sdata->local, sta->ptk);
492
	else if (sta)
J
Johannes Berg 已提交
493
		old_key = key_mtx_dereference(sdata->local, sta->gtk[idx]);
494
	else
J
Johannes Berg 已提交
495
		old_key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
496

497 498
	increment_tailroom_need_count(sdata);

499
	__ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
J
Johannes Berg 已提交
500
	__ieee80211_key_destroy(old_key);
501

J
Johannes Berg 已提交
502
	ieee80211_debugfs_key_add(key);
503

504
	ret = ieee80211_key_enable_hw_accel(key);
J
Johannes Berg 已提交
505

J
Johannes Berg 已提交
506
	mutex_unlock(&sdata->local->key_mtx);
507 508

	return ret;
509 510
}

511
void __ieee80211_key_free(struct ieee80211_key *key)
512
{
513 514 515
	if (!key)
		return;

516 517 518
	/*
	 * Replace key with nothingness if it was ever used.
	 */
J
Johannes Berg 已提交
519
	if (key->sdata)
520
		__ieee80211_key_replace(key->sdata, key->sta,
521 522
				key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
				key, NULL);
J
Johannes Berg 已提交
523
	__ieee80211_key_destroy(key);
524
}
525

526 527
void ieee80211_key_free(struct ieee80211_local *local,
			struct ieee80211_key *key)
528
{
J
Johannes Berg 已提交
529
	mutex_lock(&local->key_mtx);
J
Johannes Berg 已提交
530
	__ieee80211_key_free(key);
J
Johannes Berg 已提交
531
	mutex_unlock(&local->key_mtx);
J
Johannes Berg 已提交
532 533
}

J
Johannes Berg 已提交
534
void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
J
Johannes Berg 已提交
535 536
{
	struct ieee80211_key *key;
J
Johannes Berg 已提交
537

J
Johannes Berg 已提交
538
	ASSERT_RTNL();
J
Johannes Berg 已提交
539

540
	if (WARN_ON(!ieee80211_sdata_running(sdata)))
J
Johannes Berg 已提交
541
		return;
J
Johannes Berg 已提交
542

J
Johannes Berg 已提交
543
	mutex_lock(&sdata->local->key_mtx);
J
Johannes Berg 已提交
544

545 546 547 548
	sdata->crypto_tx_tailroom_needed_cnt = 0;

	list_for_each_entry(key, &sdata->key_list, list) {
		increment_tailroom_need_count(sdata);
J
Johannes Berg 已提交
549
		ieee80211_key_enable_hw_accel(key);
550
	}
551

J
Johannes Berg 已提交
552
	mutex_unlock(&sdata->local->key_mtx);
J
Johannes Berg 已提交
553 554
}

555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
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);
	struct ieee80211_key *key;
	struct ieee80211_sub_if_data *sdata;

	ASSERT_RTNL();

	mutex_lock(&local->key_mtx);
	if (vif) {
		sdata = vif_to_sdata(vif);
		list_for_each_entry(key, &sdata->key_list, list)
			iter(hw, &sdata->vif,
			     key->sta ? &key->sta->sta : NULL,
			     &key->conf, iter_data);
	} else {
		list_for_each_entry(sdata, &local->interfaces, list)
			list_for_each_entry(key, &sdata->key_list, list)
				iter(hw, &sdata->vif,
				     key->sta ? &key->sta->sta : NULL,
				     &key->conf, iter_data);
	}
	mutex_unlock(&local->key_mtx);
}
EXPORT_SYMBOL(ieee80211_iter_keys);

J
Johannes Berg 已提交
588
void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)
J
Johannes Berg 已提交
589 590 591
{
	struct ieee80211_key *key;

J
Johannes Berg 已提交
592
	ASSERT_RTNL();
593

J
Johannes Berg 已提交
594
	mutex_lock(&sdata->local->key_mtx);
J
Johannes Berg 已提交
595

J
Johannes Berg 已提交
596 597
	list_for_each_entry(key, &sdata->key_list, list)
		ieee80211_key_disable_hw_accel(key);
J
Johannes Berg 已提交
598

J
Johannes Berg 已提交
599
	mutex_unlock(&sdata->local->key_mtx);
600
}
J
Johannes Berg 已提交
601

602 603 604
void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_key *key, *tmp;
605

J
Johannes Berg 已提交
606
	mutex_lock(&sdata->local->key_mtx);
607

608
	ieee80211_debugfs_key_remove_mgmt_default(sdata);
609 610

	list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
J
Johannes Berg 已提交
611
		__ieee80211_key_free(key);
612

613 614
	ieee80211_debugfs_key_update_default(sdata);

J
Johannes Berg 已提交
615
	mutex_unlock(&sdata->local->key_mtx);
J
Johannes Berg 已提交
616
}
617 618 619 620 621 622 623 624 625 626 627 628


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);
629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702

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:
		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:
		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;
	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:
		if (WARN_ON(tid < 0 || tid >= NUM_RX_DATA_QUEUES))
			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:
		if (WARN_ON(tid < -1 || tid >= NUM_RX_DATA_QUEUES))
			return;
		if (tid < 0)
			pn = key->u.ccmp.rx_pn[NUM_RX_DATA_QUEUES];
		else
			pn = key->u.ccmp.rx_pn[tid];
		memcpy(seq->ccmp.pn, pn, CCMP_PN_LEN);
		break;
	case WLAN_CIPHER_SUITE_AES_CMAC:
		if (WARN_ON(tid != 0))
			return;
		pn = key->u.aes_cmac.rx_pn;
		memcpy(seq->aes_cmac.pn, pn, CMAC_PN_LEN);
		break;
	}
}
EXPORT_SYMBOL(ieee80211_get_key_rx_seq);