11f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg/*
21f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg * Copyright 2002-2005, Instant802 Networks, Inc.
31f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg * Copyright 2005-2006, Devicescape Software, Inc.
41f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
53b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * Copyright 2007-2008	Johannes Berg <johannes@sipsolutions.net>
6d98ad83ee86e523cc00cbf425f456fbd14b4fdc4Johannes Berg * Copyright 2013-2014  Intel Mobile Communications GmbH
71f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg *
81f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg * This program is free software; you can redistribute it and/or modify
91f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg * it under the terms of the GNU General Public License version 2 as
101f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg * published by the Free Software Foundation.
111f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg */
121f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg
1311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg#include <linux/if_ether.h>
1411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg#include <linux/etherdevice.h>
1511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg#include <linux/list.h>
16d4e46a3d9869563c6210b01bb651c40cbe65da80Johannes Berg#include <linux/rcupdate.h>
17db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg#include <linux/rtnetlink.h>
185a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
19bc3b2d7fb9b014d75ebb79ba371a763dbab5e8cfPaul Gortmaker#include <linux/export.h>
201f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg#include <net/mac80211.h>
21d26ad3771fe7405bf80d736cae9ba4c706a7b1d8Johannes Berg#include <asm/unaligned.h>
221f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg#include "ieee80211_i.h"
232448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg#include "driver-ops.h"
241f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg#include "debugfs_key.h"
251f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg#include "aes_ccm.h"
263cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen#include "aes_cmac.h"
271f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg
2811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
29dbbea6713d6096cd1c411cb453a6b71292c78b33Johannes Berg/**
30dbbea6713d6096cd1c411cb453a6b71292c78b33Johannes Berg * DOC: Key handling basics
3111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg *
3211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * Key handling in mac80211 is done based on per-interface (sub_if_data)
3311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * keys and per-station keys. Since each station belongs to an interface,
3411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * each station key also belongs to that interface.
3511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg *
36b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * Hardware acceleration is done on a best-effort basis for algorithms
37b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * that are implemented in software,  for each key the hardware is asked
38b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * to enable that key for offloading but if it cannot do that the key is
39b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * simply kept for software encryption (unless it is for an algorithm
40b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * that isn't implemented in software).
41b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * There is currently no way of knowing whether a key is handled in SW
42b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * or HW except by looking into debugfs.
4311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg *
44b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * All key management is internally protected by a mutex. Within all
45b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * other parts of mac80211, key references are, just as STA structure
46b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * references, protected by RCU. Note, however, that some things are
47b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * unprotected, namely the key->sta dereferences within the hardware
48b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * acceleration functions. This means that sta_info_destroy() must
49b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * remove the key which waits for an RCU grace period.
5011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg */
5111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
5211a843b7e16062389c53ba393c7913956e034eb2Johannes Bergstatic const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
5311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
54ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Bergstatic void assert_key_lock(struct ieee80211_local *local)
553b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{
5646a5ebaf02d69e26ee0f47a0b8d2d9bc619240d4Johannes Berg	lockdep_assert_held(&local->key_mtx);
573b96766f0e643f52ae19e134664df6730c737e87Johannes Berg}
583b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
593bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powarstatic void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata)
603bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar{
613bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	/*
623bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 * When this count is zero, SKB resizing for allocating tailroom
633bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 * for IV or MMIC is skipped. But, this check has created two race
643bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 * cases in xmit path while transiting from zero count to one:
653bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 *
663bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 * 1. SKB resize was skipped because no key was added but just before
673bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 * the xmit key is added and SW encryption kicks off.
683bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 *
693bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 * 2. SKB resize was skipped because all the keys were hw planted but
703bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 * just before xmit one of the key is deleted and SW encryption kicks
713bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 * off.
723bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 *
733bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 * In both the above case SW encryption will find not enough space for
743bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 * tailroom and exits with WARN_ON. (See WARN_ONs at wpa.c)
753bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 *
763bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 * Solution has been explained at
773bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 * http://mid.gmane.org/1308590980.4322.19.camel@jlt3.sipsolutions.net
783bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 */
793bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar
803bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	if (!sdata->crypto_tx_tailroom_needed_cnt++) {
813bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar		/*
823bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar		 * Flush all XMIT packets currently using HW encryption or no
833bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar		 * encryption at all if the count transition is from 0 -> 1.
843bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar		 */
853bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar		synchronize_net();
863bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	}
873bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar}
883bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar
893ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Bergstatic int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
9011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg{
91dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	struct ieee80211_sub_if_data *sdata;
9289c91caeccf45bbeb86104445125fe1eaec12079Johannes Berg	struct sta_info *sta;
9311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	int ret;
9411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
953b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	might_sleep();
963b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
9727b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	if (key->flags & KEY_FLAG_TAINTED)
9827b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		return -EINVAL;
9927b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg
100e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	if (!key->local->ops->set_key)
1013ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg		goto out_unsupported;
10211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
103ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	assert_key_lock(key->local);
104ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg
10589c91caeccf45bbeb86104445125fe1eaec12079Johannes Berg	sta = key->sta;
106dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg
107e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	/*
108e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	 * If this is a per-STA GTK, check if it
109e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	 * is supported; if not, return.
110e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	 */
111e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	if (sta && !(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE) &&
112e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	    !(key->local->hw.flags & IEEE80211_HW_SUPPORTS_PER_STA_GTK))
113e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg		goto out_unsupported;
114e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg
11589c91caeccf45bbeb86104445125fe1eaec12079Johannes Berg	if (sta && !sta->uploaded)
11689c91caeccf45bbeb86104445125fe1eaec12079Johannes Berg		goto out_unsupported;
11789c91caeccf45bbeb86104445125fe1eaec12079Johannes Berg
118dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	sdata = key->sdata;
11918890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
12018890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa		/*
12118890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa		 * The driver doesn't know anything about VLAN interfaces.
12218890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa		 * Hence, don't send GTKs for VLAN interfaces to the driver.
12318890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa		 */
12418890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa		if (!(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE))
12518890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa			goto out_unsupported;
12618890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa	}
12711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
12889c91caeccf45bbeb86104445125fe1eaec12079Johannes Berg	ret = drv_set_key(key->local, SET_KEY, sdata,
12989c91caeccf45bbeb86104445125fe1eaec12079Johannes Berg			  sta ? &sta->sta : NULL, &key->conf);
13011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
131e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	if (!ret) {
13211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
1333bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar
134ca34e3b5c808385b175650605faa29e71e91991bIdo Yariv		if (!(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC))
1353bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar			sdata->crypto_tx_tailroom_needed_cnt--;
1363bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar
137077a9154898b374f20555adc3f620cccd02581d6Arik Nemtsov		WARN_ON((key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE) &&
138077a9154898b374f20555adc3f620cccd02581d6Arik Nemtsov			(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV));
139077a9154898b374f20555adc3f620cccd02581d6Arik Nemtsov
140e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg		return 0;
141e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	}
14211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
143e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	if (ret != -ENOSPC && ret != -EOPNOTSUPP)
144bdcbd8e0e3ffdad32b14b6373e67bfcf5fd3f002Johannes Berg		sdata_err(sdata,
1450fb9a9ec27718fbf7fa3153bc94becefb716ceebJoe Perches			  "failed to set key (%d, %pM) to hardware (%d)\n",
14689c91caeccf45bbeb86104445125fe1eaec12079Johannes Berg			  key->conf.keyidx,
14789c91caeccf45bbeb86104445125fe1eaec12079Johannes Berg			  sta ? sta->sta.addr : bcast_addr, ret);
1483ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg
149e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg out_unsupported:
150e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	switch (key->conf.cipher) {
151e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	case WLAN_CIPHER_SUITE_WEP40:
152e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	case WLAN_CIPHER_SUITE_WEP104:
153e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	case WLAN_CIPHER_SUITE_TKIP:
154e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	case WLAN_CIPHER_SUITE_CCMP:
155e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	case WLAN_CIPHER_SUITE_AES_CMAC:
156e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg		/* all of these we can do in software */
157e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg		return 0;
158e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	default:
159e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg		return -EINVAL;
1603ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg	}
16111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg}
16211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
16311a843b7e16062389c53ba393c7913956e034eb2Johannes Bergstatic void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
16411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg{
165dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	struct ieee80211_sub_if_data *sdata;
16689c91caeccf45bbeb86104445125fe1eaec12079Johannes Berg	struct sta_info *sta;
16711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	int ret;
16811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
1693b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	might_sleep();
1703b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
171db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	if (!key || !key->local->ops->set_key)
17211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		return;
17311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
174ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	assert_key_lock(key->local);
175ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg
176ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
17711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		return;
17811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
17989c91caeccf45bbeb86104445125fe1eaec12079Johannes Berg	sta = key->sta;
180dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	sdata = key->sdata;
181dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg
182ca34e3b5c808385b175650605faa29e71e91991bIdo Yariv	if (!(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC))
1833bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar		increment_tailroom_need_count(sdata);
1843bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar
18512375ef933fa8271396ed0c1e318cb1bd2e2689dJohannes Berg	ret = drv_set_key(key->local, DISABLE_KEY, sdata,
18689c91caeccf45bbeb86104445125fe1eaec12079Johannes Berg			  sta ? &sta->sta : NULL, &key->conf);
18711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
18811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	if (ret)
189bdcbd8e0e3ffdad32b14b6373e67bfcf5fd3f002Johannes Berg		sdata_err(sdata,
1900fb9a9ec27718fbf7fa3153bc94becefb716ceebJoe Perches			  "failed to remove key (%d, %pM) from hardware (%d)\n",
19189c91caeccf45bbeb86104445125fe1eaec12079Johannes Berg			  key->conf.keyidx,
19289c91caeccf45bbeb86104445125fe1eaec12079Johannes Berg			  sta ? sta->sta.addr : bcast_addr, ret);
19311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
1943b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
1953b96766f0e643f52ae19e134664df6730c737e87Johannes Berg}
1963b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
1973b96766f0e643f52ae19e134664df6730c737e87Johannes Bergstatic void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
198f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg					int idx, bool uni, bool multi)
1993b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{
2003b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	struct ieee80211_key *key = NULL;
2013b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
202ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	assert_key_lock(sdata->local);
203ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg
2043b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	if (idx >= 0 && idx < NUM_DEFAULT_KEYS)
20540b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg		key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
2063b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
207de5fad815703b5b24bc4726cd71422929537d259Yoni Divinsky	if (uni) {
208f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg		rcu_assign_pointer(sdata->default_unicast_key, key);
209de5fad815703b5b24bc4726cd71422929537d259Yoni Divinsky		drv_set_default_unicast_key(sdata->local, sdata, idx);
210de5fad815703b5b24bc4726cd71422929537d259Yoni Divinsky	}
211de5fad815703b5b24bc4726cd71422929537d259Yoni Divinsky
212f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg	if (multi)
213f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg		rcu_assign_pointer(sdata->default_multicast_key, key);
2143b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
215f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg	ieee80211_debugfs_key_update_default(sdata);
2163b96766f0e643f52ae19e134664df6730c737e87Johannes Berg}
2173b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
218f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Bergvoid ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx,
219f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg			       bool uni, bool multi)
2203b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{
221ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_lock(&sdata->local->key_mtx);
222f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg	__ieee80211_set_default_key(sdata, idx, uni, multi);
223ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_unlock(&sdata->local->key_mtx);
2243b96766f0e643f52ae19e134664df6730c737e87Johannes Berg}
2253b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2263cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinenstatic void
2273cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen__ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx)
2283cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen{
2293cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	struct ieee80211_key *key = NULL;
2303cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen
231ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	assert_key_lock(sdata->local);
232ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg
2333cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	if (idx >= NUM_DEFAULT_KEYS &&
2343cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	    idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
23540b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg		key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
2363cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen
2373cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	rcu_assign_pointer(sdata->default_mgmt_key, key);
2383cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen
239f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg	ieee80211_debugfs_key_update_default(sdata);
2403cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen}
2413cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen
2423cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinenvoid ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
2433cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen				    int idx)
2443cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen{
245ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_lock(&sdata->local->key_mtx);
2463cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	__ieee80211_set_default_mgmt_key(sdata, idx);
247ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_unlock(&sdata->local->key_mtx);
2483cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen}
2493cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen
2503b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2513b8d9c290364c86fc9f4baff7c82264a96f706d6Johannes Bergstatic void ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
2523b8d9c290364c86fc9f4baff7c82264a96f706d6Johannes Berg				  struct sta_info *sta,
2533b8d9c290364c86fc9f4baff7c82264a96f706d6Johannes Berg				  bool pairwise,
2543b8d9c290364c86fc9f4baff7c82264a96f706d6Johannes Berg				  struct ieee80211_key *old,
2553b8d9c290364c86fc9f4baff7c82264a96f706d6Johannes Berg				  struct ieee80211_key *new)
2563b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{
257f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg	int idx;
258f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg	bool defunikey, defmultikey, defmgmtkey;
2593b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2605282c3ba4c5a24b2ab45a6742f9ab01a3d90c167Johannes Berg	/* caller must provide at least one old/new */
2615282c3ba4c5a24b2ab45a6742f9ab01a3d90c167Johannes Berg	if (WARN_ON(!new && !old))
2625282c3ba4c5a24b2ab45a6742f9ab01a3d90c167Johannes Berg		return;
2635282c3ba4c5a24b2ab45a6742f9ab01a3d90c167Johannes Berg
2643b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	if (new)
265f850e00fcd7767d01101e2f0a6d464bee8e48b47Johannes Berg		list_add_tail(&new->list, &sdata->key_list);
2663b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2672475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov	WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx);
2683b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2692475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov	if (old)
2702475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov		idx = old->conf.keyidx;
2712475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov	else
2722475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov		idx = new->conf.keyidx;
2733b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2742475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov	if (sta) {
2752475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov		if (pairwise) {
2762475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov			rcu_assign_pointer(sta->ptk[idx], new);
2772475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov			sta->ptk_idx = idx;
2782475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov		} else {
2792475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov			rcu_assign_pointer(sta->gtk[idx], new);
2802475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov			sta->gtk_idx = idx;
2812475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov		}
2822475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov	} else {
28340b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg		defunikey = old &&
28440b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg			old == key_mtx_dereference(sdata->local,
28540b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg						sdata->default_unicast_key);
28640b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg		defmultikey = old &&
28740b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg			old == key_mtx_dereference(sdata->local,
28840b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg						sdata->default_multicast_key);
28940b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg		defmgmtkey = old &&
29040b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg			old == key_mtx_dereference(sdata->local,
29140b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg						sdata->default_mgmt_key);
2923b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
293f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg		if (defunikey && !new)
294f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg			__ieee80211_set_default_key(sdata, -1, true, false);
295f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg		if (defmultikey && !new)
296f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg			__ieee80211_set_default_key(sdata, -1, false, true);
2973cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		if (defmgmtkey && !new)
2983cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen			__ieee80211_set_default_mgmt_key(sdata, -1);
2993b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
3003b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		rcu_assign_pointer(sdata->keys[idx], new);
301f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg		if (defunikey && new)
302f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg			__ieee80211_set_default_key(sdata, new->conf.keyidx,
303f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg						    true, false);
304f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg		if (defmultikey && new)
305f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg			__ieee80211_set_default_key(sdata, new->conf.keyidx,
306f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg						    false, true);
3073cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		if (defmgmtkey && new)
3083cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen			__ieee80211_set_default_mgmt_key(sdata,
3093cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen							 new->conf.keyidx);
3103b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	}
3113b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
312b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg	if (old)
313b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg		list_del(&old->list);
31411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg}
31511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
3162475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanovstruct ieee80211_key *
3172475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanovieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
3182475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov		    const u8 *key_data,
3192475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov		    size_t seq_len, const u8 *seq,
3202475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov		    const struct ieee80211_cipher_scheme *cs)
3211f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg{
3221f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg	struct ieee80211_key *key;
3231ac62ba7c985109868a18d959986425148481f47Ben Hutchings	int i, j, err;
3241f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg
3258c5bb1fad0bb9c29f7d817c1e2fdb052b76f04e9Johannes Berg	if (WARN_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS))
3268c5bb1fad0bb9c29f7d817c1e2fdb052b76f04e9Johannes Berg		return ERR_PTR(-EINVAL);
32711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
32811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL);
3291f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg	if (!key)
3301ac62ba7c985109868a18d959986425148481f47Ben Hutchings		return ERR_PTR(-ENOMEM);
33111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
33211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	/*
33311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	 * Default to software encryption; we'll later upload the
33411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	 * key to the hardware if possible.
33511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	 */
33611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	key->conf.flags = 0;
33711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	key->flags = 0;
33811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
33997359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg	key->conf.cipher = cipher;
34011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	key->conf.keyidx = idx;
34111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	key->conf.keylen = key_len;
34297359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg	switch (cipher) {
34397359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg	case WLAN_CIPHER_SUITE_WEP40:
34497359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg	case WLAN_CIPHER_SUITE_WEP104:
3454325f6caad98c075b39f0eaaac6693a0dd43f646Johannes Berg		key->conf.iv_len = IEEE80211_WEP_IV_LEN;
3464325f6caad98c075b39f0eaaac6693a0dd43f646Johannes Berg		key->conf.icv_len = IEEE80211_WEP_ICV_LEN;
34776708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		break;
34897359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg	case WLAN_CIPHER_SUITE_TKIP:
3494325f6caad98c075b39f0eaaac6693a0dd43f646Johannes Berg		key->conf.iv_len = IEEE80211_TKIP_IV_LEN;
3504325f6caad98c075b39f0eaaac6693a0dd43f646Johannes Berg		key->conf.icv_len = IEEE80211_TKIP_ICV_LEN;
3519f26a952210e44691f784b77bf1f83a500d63f58Jouni Malinen		if (seq) {
3525a306f5887d5fd840beb8ea872897fa89e8fcdefJohannes Berg			for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
353faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen				key->u.tkip.rx[i].iv32 =
354faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen					get_unaligned_le32(&seq[2]);
355faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen				key->u.tkip.rx[i].iv16 =
356faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen					get_unaligned_le16(seq);
357faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen			}
358faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen		}
359523b02ea23b175dd3e46e3daf1bc9354376640a3Johannes Berg		spin_lock_init(&key->u.tkip.txlock);
36076708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		break;
36197359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg	case WLAN_CIPHER_SUITE_CCMP:
3624325f6caad98c075b39f0eaaac6693a0dd43f646Johannes Berg		key->conf.iv_len = IEEE80211_CCMP_HDR_LEN;
3634325f6caad98c075b39f0eaaac6693a0dd43f646Johannes Berg		key->conf.icv_len = IEEE80211_CCMP_MIC_LEN;
3649f26a952210e44691f784b77bf1f83a500d63f58Jouni Malinen		if (seq) {
3655a306f5887d5fd840beb8ea872897fa89e8fcdefJohannes Berg			for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++)
3664325f6caad98c075b39f0eaaac6693a0dd43f646Johannes Berg				for (j = 0; j < IEEE80211_CCMP_PN_LEN; j++)
367faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen					key->u.ccmp.rx_pn[i][j] =
3684325f6caad98c075b39f0eaaac6693a0dd43f646Johannes Berg						seq[IEEE80211_CCMP_PN_LEN - j - 1];
369faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen		}
37011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		/*
37111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		 * Initialize AES key state here as an optimization so that
37211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		 * it does not need to be initialized for every packet.
37311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		 */
37411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data);
3751ac62ba7c985109868a18d959986425148481f47Ben Hutchings		if (IS_ERR(key->u.ccmp.tfm)) {
3761ac62ba7c985109868a18d959986425148481f47Ben Hutchings			err = PTR_ERR(key->u.ccmp.tfm);
3773b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			kfree(key);
3781f951a7f8ba05192291f781ef99a892697e47d62Petr Å tetiar			return ERR_PTR(err);
37911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		}
38060ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg		break;
38160ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg	case WLAN_CIPHER_SUITE_AES_CMAC:
38260ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg		key->conf.iv_len = 0;
38360ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg		key->conf.icv_len = sizeof(struct ieee80211_mmie);
38460ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg		if (seq)
3854325f6caad98c075b39f0eaaac6693a0dd43f646Johannes Berg			for (j = 0; j < IEEE80211_CMAC_PN_LEN; j++)
3860f92732344e88023807342fef4c566e0660c2fd9Johannes Berg				key->u.aes_cmac.rx_pn[j] =
3874325f6caad98c075b39f0eaaac6693a0dd43f646Johannes Berg					seq[IEEE80211_CMAC_PN_LEN - j - 1];
3883cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		/*
3893cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		 * Initialize AES key state here as an optimization so that
3903cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		 * it does not need to be initialized for every packet.
3913cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		 */
3923cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		key->u.aes_cmac.tfm =
3933cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen			ieee80211_aes_cmac_key_setup(key_data);
3941ac62ba7c985109868a18d959986425148481f47Ben Hutchings		if (IS_ERR(key->u.aes_cmac.tfm)) {
3951ac62ba7c985109868a18d959986425148481f47Ben Hutchings			err = PTR_ERR(key->u.aes_cmac.tfm);
3963cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen			kfree(key);
3971f951a7f8ba05192291f781ef99a892697e47d62Petr Å tetiar			return ERR_PTR(err);
3983cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		}
39960ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg		break;
4002475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov	default:
4012475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov		if (cs) {
4022475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov			size_t len = (seq_len > MAX_PN_LEN) ?
4032475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov						MAX_PN_LEN : seq_len;
4042475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov
4052475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov			key->conf.iv_len = cs->hdr_len;
4062475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov			key->conf.icv_len = cs->mic_len;
4072475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov			for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++)
4082475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov				for (j = 0; j < len; j++)
4092475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov					key->u.gen.rx_pn[i][j] =
4102475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov							seq[len - j - 1];
4112475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov		}
4123cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	}
41360ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg	memcpy(key->conf.key, key_data, key_len);
41460ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg	INIT_LIST_HEAD(&key->list);
4153cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen
416db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	return key;
417db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg}
41811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
41979cf2dfa362f3e6368ad8ecb10aa82b39678fedcJohannes Bergstatic void ieee80211_key_free_common(struct ieee80211_key *key)
42079cf2dfa362f3e6368ad8ecb10aa82b39678fedcJohannes Berg{
42179cf2dfa362f3e6368ad8ecb10aa82b39678fedcJohannes Berg	if (key->conf.cipher == WLAN_CIPHER_SUITE_CCMP)
42279cf2dfa362f3e6368ad8ecb10aa82b39678fedcJohannes Berg		ieee80211_aes_key_free(key->u.ccmp.tfm);
42379cf2dfa362f3e6368ad8ecb10aa82b39678fedcJohannes Berg	if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC)
42479cf2dfa362f3e6368ad8ecb10aa82b39678fedcJohannes Berg		ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
42529c3f9c3996abea060fa6e0b9e6a30d3f0cc828cJohannes Berg	kzfree(key);
42679cf2dfa362f3e6368ad8ecb10aa82b39678fedcJohannes Berg}
42779cf2dfa362f3e6368ad8ecb10aa82b39678fedcJohannes Berg
4286d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Bergstatic void __ieee80211_key_destroy(struct ieee80211_key *key,
4296d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg				    bool delay_tailroom)
430ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg{
43132162a4dab0e6a4ca7f886a01173b5f9b80843beJouni Malinen	if (key->local)
43232162a4dab0e6a4ca7f886a01173b5f9b80843beJouni Malinen		ieee80211_key_disable_hw_accel(key);
433ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg
4343bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	if (key->local) {
4358d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg		struct ieee80211_sub_if_data *sdata = key->sdata;
4368d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg
43732162a4dab0e6a4ca7f886a01173b5f9b80843beJouni Malinen		ieee80211_debugfs_key_remove(key);
4388d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg
4398d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg		if (delay_tailroom) {
4408d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg			/* see ieee80211_delayed_tailroom_dec */
4418d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg			sdata->crypto_tx_tailroom_pending_dec++;
4428d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg			schedule_delayed_work(&sdata->dec_tailroom_needed_wk,
4438d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg					      HZ/2);
4448d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg		} else {
4458d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg			sdata->crypto_tx_tailroom_needed_cnt--;
4468d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg		}
4473bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	}
448ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg
44979cf2dfa362f3e6368ad8ecb10aa82b39678fedcJohannes Berg	ieee80211_key_free_common(key);
45079cf2dfa362f3e6368ad8ecb10aa82b39678fedcJohannes Berg}
45179cf2dfa362f3e6368ad8ecb10aa82b39678fedcJohannes Berg
4526d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Bergstatic void ieee80211_key_destroy(struct ieee80211_key *key,
4536d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg				  bool delay_tailroom)
4546d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg{
4556d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg	if (!key)
4566d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg		return;
4576d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg
4586d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg	/*
4596d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg	 * Synchronize so the TX path can no longer be using
4606d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg	 * this key before we free/remove it.
4616d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg	 */
4626d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg	synchronize_net();
4636d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg
4646d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg	__ieee80211_key_destroy(key, delay_tailroom);
4656d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg}
4666d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg
46779cf2dfa362f3e6368ad8ecb10aa82b39678fedcJohannes Bergvoid ieee80211_key_free_unused(struct ieee80211_key *key)
46879cf2dfa362f3e6368ad8ecb10aa82b39678fedcJohannes Berg{
46979cf2dfa362f3e6368ad8ecb10aa82b39678fedcJohannes Berg	WARN_ON(key->sdata || key->local);
47079cf2dfa362f3e6368ad8ecb10aa82b39678fedcJohannes Berg	ieee80211_key_free_common(key);
471ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg}
472ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg
4733ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Bergint ieee80211_key_link(struct ieee80211_key *key,
4743ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg		       struct ieee80211_sub_if_data *sdata,
4753ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg		       struct sta_info *sta)
476db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg{
47727b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	struct ieee80211_local *local = sdata->local;
478db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	struct ieee80211_key *old_key;
4793ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg	int idx, ret;
48067aa030c0dff6095128bcb4e8043b48360f32331Mariusz Kozlowski	bool pairwise;
481db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg
48267aa030c0dff6095128bcb4e8043b48360f32331Mariusz Kozlowski	pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE;
483db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	idx = key->conf.keyidx;
484db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	key->local = sdata->local;
485db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	key->sdata = sdata;
486db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	key->sta = sta;
487db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg
488ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_lock(&sdata->local->key_mtx);
4893b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
490e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	if (sta && pairwise)
4912475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov		old_key = key_mtx_dereference(sdata->local, sta->ptk[idx]);
492e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	else if (sta)
49340b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg		old_key = key_mtx_dereference(sdata->local, sta->gtk[idx]);
494d4e46a3d9869563c6210b01bb651c40cbe65da80Johannes Berg	else
49540b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg		old_key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
496db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg
4973bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	increment_tailroom_need_count(sdata);
4983bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar
4993b8d9c290364c86fc9f4baff7c82264a96f706d6Johannes Berg	ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
5003b8d9c290364c86fc9f4baff7c82264a96f706d6Johannes Berg	ieee80211_key_destroy(old_key, true);
501d4e46a3d9869563c6210b01bb651c40cbe65da80Johannes Berg
502ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	ieee80211_debugfs_key_add(key);
503db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg
50427b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	if (!local->wowlan) {
50527b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		ret = ieee80211_key_enable_hw_accel(key);
50627b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		if (ret)
50727b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg			ieee80211_key_free(key, true);
50827b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	} else {
50927b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		ret = 0;
51027b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	}
51179cf2dfa362f3e6368ad8ecb10aa82b39678fedcJohannes Berg
512ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_unlock(&sdata->local->key_mtx);
5133ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg
5143ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg	return ret;
5151f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg}
5161f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg
5173b8d9c290364c86fc9f4baff7c82264a96f706d6Johannes Bergvoid ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom)
5181f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg{
5195c0c36412b2dc6b1e243c7e9115306fe286583b7Johannes Berg	if (!key)
5205c0c36412b2dc6b1e243c7e9115306fe286583b7Johannes Berg		return;
5215c0c36412b2dc6b1e243c7e9115306fe286583b7Johannes Berg
5223b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	/*
5233b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	 * Replace key with nothingness if it was ever used.
5243b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	 */
5253a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg	if (key->sdata)
5263b8d9c290364c86fc9f4baff7c82264a96f706d6Johannes Berg		ieee80211_key_replace(key->sdata, key->sta,
527e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg				key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
528e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg				key, NULL);
5293b8d9c290364c86fc9f4baff7c82264a96f706d6Johannes Berg	ieee80211_key_destroy(key, delay_tailroom);
5303b96766f0e643f52ae19e134664df6730c737e87Johannes Berg}
531d4e46a3d9869563c6210b01bb651c40cbe65da80Johannes Berg
532ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Bergvoid ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
5333a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg{
5343a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg	struct ieee80211_key *key;
53511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
5363a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg	ASSERT_RTNL();
53711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
5389607e6b66a0d25ca63b70d54a4283fa13d8f7c9dJohannes Berg	if (WARN_ON(!ieee80211_sdata_running(sdata)))
5393a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg		return;
54011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
541ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_lock(&sdata->local->key_mtx);
54211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
5433bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	sdata->crypto_tx_tailroom_needed_cnt = 0;
5443bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar
5453bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	list_for_each_entry(key, &sdata->key_list, list) {
5463bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar		increment_tailroom_need_count(sdata);
547ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg		ieee80211_key_enable_hw_accel(key);
5483bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	}
5493b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
550ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_unlock(&sdata->local->key_mtx);
55111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg}
55211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
553830af02f24fbc087999b757b8eca51829c67fa6fJohannes Bergvoid ieee80211_iter_keys(struct ieee80211_hw *hw,
554830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg			 struct ieee80211_vif *vif,
555830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg			 void (*iter)(struct ieee80211_hw *hw,
556830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg				      struct ieee80211_vif *vif,
557830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg				      struct ieee80211_sta *sta,
558830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg				      struct ieee80211_key_conf *key,
559830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg				      void *data),
560830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg			 void *iter_data)
561830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg{
562830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg	struct ieee80211_local *local = hw_to_local(hw);
56327b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	struct ieee80211_key *key, *tmp;
564830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg	struct ieee80211_sub_if_data *sdata;
565830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg
566830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg	ASSERT_RTNL();
567830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg
568830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg	mutex_lock(&local->key_mtx);
569830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg	if (vif) {
570830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg		sdata = vif_to_sdata(vif);
57127b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
572830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg			iter(hw, &sdata->vif,
573830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg			     key->sta ? &key->sta->sta : NULL,
574830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg			     &key->conf, iter_data);
575830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg	} else {
576830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg		list_for_each_entry(sdata, &local->interfaces, list)
57727b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg			list_for_each_entry_safe(key, tmp,
57827b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg						 &sdata->key_list, list)
579830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg				iter(hw, &sdata->vif,
580830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg				     key->sta ? &key->sta->sta : NULL,
581830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg				     &key->conf, iter_data);
582830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg	}
583830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg	mutex_unlock(&local->key_mtx);
584830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg}
585830af02f24fbc087999b757b8eca51829c67fa6fJohannes BergEXPORT_SYMBOL(ieee80211_iter_keys);
586830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg
5877907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Bergstatic void ieee80211_free_keys_iface(struct ieee80211_sub_if_data *sdata,
5887907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg				      struct list_head *keys)
5893b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{
5903b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	struct ieee80211_key *key, *tmp;
5913b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
5928d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg	sdata->crypto_tx_tailroom_needed_cnt -=
5938d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg		sdata->crypto_tx_tailroom_pending_dec;
5948d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg	sdata->crypto_tx_tailroom_pending_dec = 0;
5958d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg
5963cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	ieee80211_debugfs_key_remove_mgmt_default(sdata);
5973b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
5986d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg	list_for_each_entry_safe(key, tmp, &sdata->key_list, list) {
5996d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg		ieee80211_key_replace(key->sdata, key->sta,
6006d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg				key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
6016d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg				key, NULL);
6027907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg		list_add_tail(&key->list, keys);
6036d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg	}
6043b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
605f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg	ieee80211_debugfs_key_update_default(sdata);
6067907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg}
607f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg
6087907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Bergvoid ieee80211_free_keys(struct ieee80211_sub_if_data *sdata,
6097907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg			 bool force_synchronize)
6107907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg{
6117907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg	struct ieee80211_local *local = sdata->local;
6127907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg	struct ieee80211_sub_if_data *vlan;
6137907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg	struct ieee80211_key *key, *tmp;
6147907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg	LIST_HEAD(keys);
6157907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg
6167907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg	cancel_delayed_work_sync(&sdata->dec_tailroom_needed_wk);
6177907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg
6187907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg	mutex_lock(&local->key_mtx);
6197907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg
6207907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg	ieee80211_free_keys_iface(sdata, &keys);
6217907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg
6227907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg	if (sdata->vif.type == NL80211_IFTYPE_AP) {
6237907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg		list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
6247907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg			ieee80211_free_keys_iface(vlan, &keys);
6256d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg	}
6266d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg
6277907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg	if (!list_empty(&keys) || force_synchronize)
6287907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg		synchronize_net();
6297907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg	list_for_each_entry_safe(key, tmp, &keys, list)
6307907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg		__ieee80211_key_destroy(key, false);
6317907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg
6328d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg	WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt ||
6338d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg		     sdata->crypto_tx_tailroom_pending_dec);
6347907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg	if (sdata->vif.type == NL80211_IFTYPE_AP) {
6357907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg		list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
6367907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg			WARN_ON_ONCE(vlan->crypto_tx_tailroom_needed_cnt ||
6377907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg				     vlan->crypto_tx_tailroom_pending_dec);
6387907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg	}
6398d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg
6407907c7d33c3733b2265dadc6385fe028af72b4c7Johannes Berg	mutex_unlock(&local->key_mtx);
64111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg}
642c68f4b892c241bdddeb6f1c1864ac26197229471Johannes Berg
6436d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Bergvoid ieee80211_free_sta_keys(struct ieee80211_local *local,
6446d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg			     struct sta_info *sta)
6456d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg{
646c87820784454bbf7fc63a9e7d9c36762a46f393cJohannes Berg	struct ieee80211_key *key;
6476d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg	int i;
6486d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg
6496d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg	mutex_lock(&local->key_mtx);
6506d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg	for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
6516d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg		key = key_mtx_dereference(local, sta->gtk[i]);
6526d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg		if (!key)
6536d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg			continue;
6546d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg		ieee80211_key_replace(key->sdata, key->sta,
6556d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg				key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
6566d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg				key, NULL);
657c87820784454bbf7fc63a9e7d9c36762a46f393cJohannes Berg		__ieee80211_key_destroy(key, true);
6586d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg	}
6596d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg
6602475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov	for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
6612475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov		key = key_mtx_dereference(local, sta->ptk[i]);
6622475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov		if (!key)
6632475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov			continue;
6646d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg		ieee80211_key_replace(key->sdata, key->sta,
6656d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg				key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
6666d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg				key, NULL);
6676d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg		__ieee80211_key_destroy(key, true);
668c87820784454bbf7fc63a9e7d9c36762a46f393cJohannes Berg	}
6696d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg
6706d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg	mutex_unlock(&local->key_mtx);
6716d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg}
6726d10e46be5ac1d0ae787babd3dafd52b30686db5Johannes Berg
6738d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Bergvoid ieee80211_delayed_tailroom_dec(struct work_struct *wk)
6748d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg{
6758d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg	struct ieee80211_sub_if_data *sdata;
6768d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg
6778d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg	sdata = container_of(wk, struct ieee80211_sub_if_data,
6788d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg			     dec_tailroom_needed_wk.work);
6798d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg
6808d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg	/*
6818d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg	 * The reason for the delayed tailroom needed decrementing is to
6828d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg	 * make roaming faster: during roaming, all keys are first deleted
6838d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg	 * and then new keys are installed. The first new key causes the
6848d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg	 * crypto_tx_tailroom_needed_cnt to go from 0 to 1, which invokes
6858d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg	 * the cost of synchronize_net() (which can be slow). Avoid this
6868d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg	 * by deferring the crypto_tx_tailroom_needed_cnt decrementing on
6878d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg	 * key removal for a while, so if we roam the value is larger than
6888d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg	 * zero and no 0->1 transition happens.
6898d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg	 *
6908d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg	 * The cost is that if the AP switching was from an AP with keys
6918d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg	 * to one without, we still allocate tailroom while it would no
6928d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg	 * longer be needed. However, in the typical (fast) roaming case
6938d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg	 * within an ESS this usually won't happen.
6948d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg	 */
6958d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg
6968d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg	mutex_lock(&sdata->local->key_mtx);
6978d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg	sdata->crypto_tx_tailroom_needed_cnt -=
6988d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg		sdata->crypto_tx_tailroom_pending_dec;
6998d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg	sdata->crypto_tx_tailroom_pending_dec = 0;
7008d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg	mutex_unlock(&sdata->local->key_mtx);
7018d1f7ecd2af55c0c82ffd2bff0ef0b26f16ea69fJohannes Berg}
702c68f4b892c241bdddeb6f1c1864ac26197229471Johannes Berg
703c68f4b892c241bdddeb6f1c1864ac26197229471Johannes Bergvoid ieee80211_gtk_rekey_notify(struct ieee80211_vif *vif, const u8 *bssid,
704c68f4b892c241bdddeb6f1c1864ac26197229471Johannes Berg				const u8 *replay_ctr, gfp_t gfp)
705c68f4b892c241bdddeb6f1c1864ac26197229471Johannes Berg{
706c68f4b892c241bdddeb6f1c1864ac26197229471Johannes Berg	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
707c68f4b892c241bdddeb6f1c1864ac26197229471Johannes Berg
708c68f4b892c241bdddeb6f1c1864ac26197229471Johannes Berg	trace_api_gtk_rekey_notify(sdata, bssid, replay_ctr);
709c68f4b892c241bdddeb6f1c1864ac26197229471Johannes Berg
710c68f4b892c241bdddeb6f1c1864ac26197229471Johannes Berg	cfg80211_gtk_rekey_notify(sdata->dev, bssid, replay_ctr, gfp);
711c68f4b892c241bdddeb6f1c1864ac26197229471Johannes Berg}
712c68f4b892c241bdddeb6f1c1864ac26197229471Johannes BergEXPORT_SYMBOL_GPL(ieee80211_gtk_rekey_notify);
7133ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg
7143ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Bergvoid ieee80211_get_key_tx_seq(struct ieee80211_key_conf *keyconf,
7153ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg			      struct ieee80211_key_seq *seq)
7163ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg{
7173ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg	struct ieee80211_key *key;
7183ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg	u64 pn64;
7193ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg
7203ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg	if (WARN_ON(!(keyconf->flags & IEEE80211_KEY_FLAG_GENERATE_IV)))
7213ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		return;
7223ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg
7233ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg	key = container_of(keyconf, struct ieee80211_key, conf);
7243ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg
7253ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg	switch (key->conf.cipher) {
7263ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg	case WLAN_CIPHER_SUITE_TKIP:
7273ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		seq->tkip.iv32 = key->u.tkip.tx.iv32;
7283ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		seq->tkip.iv16 = key->u.tkip.tx.iv16;
7293ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		break;
7303ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg	case WLAN_CIPHER_SUITE_CCMP:
7313ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		pn64 = atomic64_read(&key->u.ccmp.tx_pn);
7323ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		seq->ccmp.pn[5] = pn64;
7333ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		seq->ccmp.pn[4] = pn64 >> 8;
7343ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		seq->ccmp.pn[3] = pn64 >> 16;
7353ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		seq->ccmp.pn[2] = pn64 >> 24;
7363ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		seq->ccmp.pn[1] = pn64 >> 32;
7373ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		seq->ccmp.pn[0] = pn64 >> 40;
7383ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		break;
7393ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg	case WLAN_CIPHER_SUITE_AES_CMAC:
7403ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		pn64 = atomic64_read(&key->u.aes_cmac.tx_pn);
7413ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		seq->ccmp.pn[5] = pn64;
7423ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		seq->ccmp.pn[4] = pn64 >> 8;
7433ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		seq->ccmp.pn[3] = pn64 >> 16;
7443ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		seq->ccmp.pn[2] = pn64 >> 24;
7453ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		seq->ccmp.pn[1] = pn64 >> 32;
7463ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		seq->ccmp.pn[0] = pn64 >> 40;
7473ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		break;
7483ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg	default:
7493ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		WARN_ON(1);
7503ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg	}
7513ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg}
7523ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes BergEXPORT_SYMBOL(ieee80211_get_key_tx_seq);
7533ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg
7543ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Bergvoid ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf,
7553ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg			      int tid, struct ieee80211_key_seq *seq)
7563ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg{
7573ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg	struct ieee80211_key *key;
7583ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg	const u8 *pn;
7593ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg
7603ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg	key = container_of(keyconf, struct ieee80211_key, conf);
7613ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg
7623ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg	switch (key->conf.cipher) {
7633ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg	case WLAN_CIPHER_SUITE_TKIP:
7645a306f5887d5fd840beb8ea872897fa89e8fcdefJohannes Berg		if (WARN_ON(tid < 0 || tid >= IEEE80211_NUM_TIDS))
7653ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg			return;
7663ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		seq->tkip.iv32 = key->u.tkip.rx[tid].iv32;
7673ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		seq->tkip.iv16 = key->u.tkip.rx[tid].iv16;
7683ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		break;
7693ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg	case WLAN_CIPHER_SUITE_CCMP:
7705a306f5887d5fd840beb8ea872897fa89e8fcdefJohannes Berg		if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS))
7713ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg			return;
7723ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		if (tid < 0)
7735a306f5887d5fd840beb8ea872897fa89e8fcdefJohannes Berg			pn = key->u.ccmp.rx_pn[IEEE80211_NUM_TIDS];
7743ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		else
7753ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg			pn = key->u.ccmp.rx_pn[tid];
7764325f6caad98c075b39f0eaaac6693a0dd43f646Johannes Berg		memcpy(seq->ccmp.pn, pn, IEEE80211_CCMP_PN_LEN);
7773ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		break;
7783ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg	case WLAN_CIPHER_SUITE_AES_CMAC:
7793ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		if (WARN_ON(tid != 0))
7803ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg			return;
7813ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		pn = key->u.aes_cmac.rx_pn;
7824325f6caad98c075b39f0eaaac6693a0dd43f646Johannes Berg		memcpy(seq->aes_cmac.pn, pn, IEEE80211_CMAC_PN_LEN);
7833ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg		break;
7843ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg	}
7853ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes Berg}
7863ea542d3c2862142ae511fac5ce2dfc7419dcc53Johannes BergEXPORT_SYMBOL(ieee80211_get_key_rx_seq);
78727b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg
78827b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Bergvoid ieee80211_set_key_tx_seq(struct ieee80211_key_conf *keyconf,
78927b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg			      struct ieee80211_key_seq *seq)
79027b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg{
79127b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	struct ieee80211_key *key;
79227b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	u64 pn64;
79327b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg
79427b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	key = container_of(keyconf, struct ieee80211_key, conf);
79527b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg
79627b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	switch (key->conf.cipher) {
79727b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	case WLAN_CIPHER_SUITE_TKIP:
79827b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		key->u.tkip.tx.iv32 = seq->tkip.iv32;
79927b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		key->u.tkip.tx.iv16 = seq->tkip.iv16;
80027b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		break;
80127b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	case WLAN_CIPHER_SUITE_CCMP:
80227b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		pn64 = (u64)seq->ccmp.pn[5] |
80327b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		       ((u64)seq->ccmp.pn[4] << 8) |
80427b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		       ((u64)seq->ccmp.pn[3] << 16) |
80527b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		       ((u64)seq->ccmp.pn[2] << 24) |
80627b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		       ((u64)seq->ccmp.pn[1] << 32) |
80727b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		       ((u64)seq->ccmp.pn[0] << 40);
80827b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		atomic64_set(&key->u.ccmp.tx_pn, pn64);
80927b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		break;
81027b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	case WLAN_CIPHER_SUITE_AES_CMAC:
81127b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		pn64 = (u64)seq->aes_cmac.pn[5] |
81227b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		       ((u64)seq->aes_cmac.pn[4] << 8) |
81327b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		       ((u64)seq->aes_cmac.pn[3] << 16) |
81427b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		       ((u64)seq->aes_cmac.pn[2] << 24) |
81527b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		       ((u64)seq->aes_cmac.pn[1] << 32) |
81627b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		       ((u64)seq->aes_cmac.pn[0] << 40);
81727b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		atomic64_set(&key->u.aes_cmac.tx_pn, pn64);
81827b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		break;
81927b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	default:
82027b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		WARN_ON(1);
82127b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		break;
82227b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	}
82327b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg}
82427b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes BergEXPORT_SYMBOL_GPL(ieee80211_set_key_tx_seq);
82527b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg
82627b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Bergvoid ieee80211_set_key_rx_seq(struct ieee80211_key_conf *keyconf,
82727b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg			      int tid, struct ieee80211_key_seq *seq)
82827b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg{
82927b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	struct ieee80211_key *key;
83027b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	u8 *pn;
83127b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg
83227b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	key = container_of(keyconf, struct ieee80211_key, conf);
83327b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg
83427b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	switch (key->conf.cipher) {
83527b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	case WLAN_CIPHER_SUITE_TKIP:
83627b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		if (WARN_ON(tid < 0 || tid >= IEEE80211_NUM_TIDS))
83727b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg			return;
83827b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		key->u.tkip.rx[tid].iv32 = seq->tkip.iv32;
83927b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		key->u.tkip.rx[tid].iv16 = seq->tkip.iv16;
84027b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		break;
84127b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	case WLAN_CIPHER_SUITE_CCMP:
84227b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS))
84327b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg			return;
84427b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		if (tid < 0)
84527b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg			pn = key->u.ccmp.rx_pn[IEEE80211_NUM_TIDS];
84627b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		else
84727b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg			pn = key->u.ccmp.rx_pn[tid];
84827b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		memcpy(pn, seq->ccmp.pn, IEEE80211_CCMP_PN_LEN);
84927b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		break;
85027b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	case WLAN_CIPHER_SUITE_AES_CMAC:
85127b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		if (WARN_ON(tid != 0))
85227b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg			return;
85327b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		pn = key->u.aes_cmac.rx_pn;
85427b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		memcpy(pn, seq->aes_cmac.pn, IEEE80211_CMAC_PN_LEN);
85527b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		break;
85627b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	default:
85727b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		WARN_ON(1);
85827b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		break;
85927b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	}
86027b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg}
86127b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes BergEXPORT_SYMBOL_GPL(ieee80211_set_key_rx_seq);
86227b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg
86327b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Bergvoid ieee80211_remove_key(struct ieee80211_key_conf *keyconf)
86427b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg{
86527b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	struct ieee80211_key *key;
86627b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg
86727b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	key = container_of(keyconf, struct ieee80211_key, conf);
86827b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg
86927b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	assert_key_lock(key->local);
87027b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg
87127b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	/*
87227b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	 * if key was uploaded, we assume the driver will/has remove(d)
87327b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	 * it, so adjust bookkeeping accordingly
87427b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	 */
87527b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
87627b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
87727b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg
878ca34e3b5c808385b175650605faa29e71e91991bIdo Yariv		if (!(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC))
87927b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg			increment_tailroom_need_count(key->sdata);
88027b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	}
88127b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg
88227b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	ieee80211_key_free(key, false);
88327b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg}
88427b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes BergEXPORT_SYMBOL_GPL(ieee80211_remove_key);
88527b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg
88627b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Bergstruct ieee80211_key_conf *
88727b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Bergieee80211_gtk_rekey_add(struct ieee80211_vif *vif,
88827b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg			struct ieee80211_key_conf *keyconf)
88927b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg{
89027b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
89127b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	struct ieee80211_local *local = sdata->local;
89227b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	struct ieee80211_key *key;
89327b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	int err;
89427b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg
89527b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	if (WARN_ON(!local->wowlan))
89627b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		return ERR_PTR(-EINVAL);
89727b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg
89827b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
89927b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		return ERR_PTR(-EINVAL);
90027b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg
90127b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	key = ieee80211_key_alloc(keyconf->cipher, keyconf->keyidx,
90227b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg				  keyconf->keylen, keyconf->key,
9032475b1cc0d5283a33144b79f3eba6d401d873962Max Stepanov				  0, NULL, NULL);
90427b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	if (IS_ERR(key))
905c5dc164df6187e845f1a7c0542f5106c74ff5a92Johannes Berg		return ERR_CAST(key);
90627b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg
90727b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	if (sdata->u.mgd.mfp != IEEE80211_MFP_DISABLED)
90827b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT;
90927b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg
91027b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	err = ieee80211_key_link(key, sdata, NULL);
91127b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	if (err)
91227b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg		return ERR_PTR(err);
91327b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg
91427b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg	return &key->conf;
91527b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes Berg}
91627b3eb9c06a7193bdc9800cd00764a130343bc8aJohannes BergEXPORT_SYMBOL_GPL(ieee80211_gtk_rekey_add);
917