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
#include <linux/export.h>
19 20
#include <net/mac80211.h>
#include "ieee80211_i.h"
21
#include "driver-ops.h"
22 23
#include "debugfs_key.h"
#include "aes_ccm.h"
24
#include "aes_cmac.h"
25

J
Johannes Berg 已提交
26

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

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

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

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

62
	return NULL;
J
Johannes Berg 已提交
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 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
	 */

	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();
	}
}

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

101 102
	might_sleep();

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

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

108 109
	sta = get_sta_for_key(key);

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

118
	sdata = key->sdata;
119 120 121 122 123 124 125 126
	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;
	}
J
Johannes Berg 已提交
127

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

130
	if (!ret) {
J
Johannes Berg 已提交
131
		key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
132 133

		if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
134 135
		      (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) ||
		      (key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)))
136 137
			sdata->crypto_tx_tailroom_needed_cnt--;

138 139 140
		WARN_ON((key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE) &&
			(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV));

141 142
		return 0;
	}
J
Johannes Berg 已提交
143

144
	if (ret != -ENOSPC && ret != -EOPNOTSUPP)
J
Joe Perches 已提交
145 146 147
		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);
148

149 150 151 152 153 154 155 156 157 158 159
 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;
160
	}
J
Johannes Berg 已提交
161 162 163 164
}

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

169 170
	might_sleep();

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

J
Johannes Berg 已提交
174 175 176
	assert_key_lock(key->local);

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

179 180 181
	sta = get_sta_for_key(key);
	sdata = key->sdata;

182
	if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
183 184
	      (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) ||
	      (key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)))
185 186
		increment_tailroom_need_count(sdata);

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

	if (ret)
J
Joe Perches 已提交
191 192 193
		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 已提交
194

195 196 197
	key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
}

198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
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);

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

J
Johannes Berg 已提交
223 224
	assert_key_lock(sdata->local);

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

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

233
	ieee80211_debugfs_key_update_default(sdata);
234 235
}

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

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

J
Johannes Berg 已提交
249 250
	assert_key_lock(sdata->local);

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

	rcu_assign_pointer(sdata->default_mgmt_key, key);

257
	ieee80211_debugfs_key_update_default(sdata);
258 259 260 261 262
}

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

268 269 270

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

	if (new)
279
		list_add_tail(&new->list, &sdata->key_list);
280

281 282 283 284 285 286 287 288
	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);
289 290 291 292 293 294 295 296
	} 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 已提交
297 298 299 300 301 302 303 304 305
		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);
306

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

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

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

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

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

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

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

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

414 415
	return key;
}
J
Johannes Berg 已提交
416

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

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

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

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

	kfree(key);
}

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

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

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

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

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

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

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

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

495 496
	increment_tailroom_need_count(sdata);

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

J
Johannes Berg 已提交
500
	ieee80211_debugfs_key_add(key);
501

502
	ret = ieee80211_key_enable_hw_accel(key);
J
Johannes Berg 已提交
503

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

	return ret;
507 508
}

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

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

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

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

J
Johannes Berg 已提交
536
	ASSERT_RTNL();
J
Johannes Berg 已提交
537

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

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

543 544 545 546
	sdata->crypto_tx_tailroom_needed_cnt = 0;

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

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

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
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 已提交
586
void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)
J
Johannes Berg 已提交
587 588 589
{
	struct ieee80211_key *key;

J
Johannes Berg 已提交
590
	ASSERT_RTNL();
591

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

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

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

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

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

606
	ieee80211_debugfs_key_remove_mgmt_default(sdata);
607 608

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

611 612
	ieee80211_debugfs_key_update_default(sdata);

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


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);
627 628 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

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);