key.c revision 523b02ea23b175dd3e46e3daf1bc9354376640a3
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>
61f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg *
71f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg * This program is free software; you can redistribute it and/or modify
81f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg * it under the terms of the GNU General Public License version 2 as
91f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg * published by the Free Software Foundation.
101f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg */
111f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg
1211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg#include <linux/if_ether.h>
1311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg#include <linux/etherdevice.h>
1411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg#include <linux/list.h>
15d4e46a3d9869563c6210b01bb651c40cbe65da80Johannes Berg#include <linux/rcupdate.h>
16db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg#include <linux/rtnetlink.h>
175a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
181f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg#include <net/mac80211.h>
191f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg#include "ieee80211_i.h"
202448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg#include "driver-ops.h"
211f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg#include "debugfs_key.h"
221f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg#include "aes_ccm.h"
233cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen#include "aes_cmac.h"
241f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg
2511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
26dbbea6713d6096cd1c411cb453a6b71292c78b33Johannes Berg/**
27dbbea6713d6096cd1c411cb453a6b71292c78b33Johannes Berg * DOC: Key handling basics
2811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg *
2911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * Key handling in mac80211 is done based on per-interface (sub_if_data)
3011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * keys and per-station keys. Since each station belongs to an interface,
3111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * each station key also belongs to that interface.
3211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg *
33b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * Hardware acceleration is done on a best-effort basis for algorithms
34b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * that are implemented in software,  for each key the hardware is asked
35b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * to enable that key for offloading but if it cannot do that the key is
36b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * simply kept for software encryption (unless it is for an algorithm
37b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * that isn't implemented in software).
38b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * There is currently no way of knowing whether a key is handled in SW
39b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * or HW except by looking into debugfs.
4011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg *
41b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * All key management is internally protected by a mutex. Within all
42b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * other parts of mac80211, key references are, just as STA structure
43b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * references, protected by RCU. Note, however, that some things are
44b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * unprotected, namely the key->sta dereferences within the hardware
45b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * acceleration functions. This means that sta_info_destroy() must
46b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * remove the key which waits for an RCU grace period.
4711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg */
4811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
4911a843b7e16062389c53ba393c7913956e034eb2Johannes Bergstatic const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
5011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
51ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Bergstatic void assert_key_lock(struct ieee80211_local *local)
523b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{
5346a5ebaf02d69e26ee0f47a0b8d2d9bc619240d4Johannes Berg	lockdep_assert_held(&local->key_mtx);
543b96766f0e643f52ae19e134664df6730c737e87Johannes Berg}
553b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
56dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Bergstatic struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key)
5711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg{
5811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	if (key->sta)
59dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg		return &key->sta->sta;
6011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
61dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	return NULL;
6211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg}
6311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
643bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powarstatic void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata)
653bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar{
663bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	/*
673bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 * When this count is zero, SKB resizing for allocating tailroom
683bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 * for IV or MMIC is skipped. But, this check has created two race
693bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 * cases in xmit path while transiting from zero count to one:
703bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 *
713bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 * 1. SKB resize was skipped because no key was added but just before
723bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 * the xmit key is added and SW encryption kicks off.
733bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 *
743bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 * 2. SKB resize was skipped because all the keys were hw planted but
753bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 * just before xmit one of the key is deleted and SW encryption kicks
763bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 * off.
773bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 *
783bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 * In both the above case SW encryption will find not enough space for
793bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 * tailroom and exits with WARN_ON. (See WARN_ONs at wpa.c)
803bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 *
813bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 * Solution has been explained at
823bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 * http://mid.gmane.org/1308590980.4322.19.camel@jlt3.sipsolutions.net
833bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	 */
843bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar
853bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	if (!sdata->crypto_tx_tailroom_needed_cnt++) {
863bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar		/*
873bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar		 * Flush all XMIT packets currently using HW encryption or no
883bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar		 * encryption at all if the count transition is from 0 -> 1.
893bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar		 */
903bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar		synchronize_net();
913bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	}
923bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar}
933bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar
943ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Bergstatic int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
9511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg{
96dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	struct ieee80211_sub_if_data *sdata;
97dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	struct ieee80211_sta *sta;
9811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	int ret;
9911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
1003b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	might_sleep();
1013b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
102e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	if (!key->local->ops->set_key)
1033ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg		goto out_unsupported;
10411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
105ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	assert_key_lock(key->local);
106ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg
107dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	sta = get_sta_for_key(key);
108dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg
109e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	/*
110e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	 * If this is a per-STA GTK, check if it
111e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	 * is supported; if not, return.
112e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	 */
113e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	if (sta && !(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE) &&
114e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	    !(key->local->hw.flags & IEEE80211_HW_SUPPORTS_PER_STA_GTK))
115e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg		goto out_unsupported;
116e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg
117dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	sdata = key->sdata;
11818890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
11918890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa		/*
12018890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa		 * The driver doesn't know anything about VLAN interfaces.
12118890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa		 * Hence, don't send GTKs for VLAN interfaces to the driver.
12218890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa		 */
12318890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa		if (!(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE))
12418890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa			goto out_unsupported;
125dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg		sdata = container_of(sdata->bss,
126dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg				     struct ieee80211_sub_if_data,
127dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg				     u.ap);
12818890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa	}
12911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
13012375ef933fa8271396ed0c1e318cb1bd2e2689dJohannes Berg	ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf);
13111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
132e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	if (!ret) {
13311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
1343bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar
1353bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar		if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
1363bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar		      (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)))
1373bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar			sdata->crypto_tx_tailroom_needed_cnt--;
1383bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar
139e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg		return 0;
140e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	}
14111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
142e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	if (ret != -ENOSPC && ret != -EOPNOTSUPP)
1430fb9a9ec27718fbf7fa3153bc94becefb716ceebJoe Perches		wiphy_err(key->local->hw.wiphy,
1440fb9a9ec27718fbf7fa3153bc94becefb716ceebJoe Perches			  "failed to set key (%d, %pM) to hardware (%d)\n",
1450fb9a9ec27718fbf7fa3153bc94becefb716ceebJoe Perches			  key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
1463ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg
147e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg out_unsupported:
148e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	switch (key->conf.cipher) {
149e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	case WLAN_CIPHER_SUITE_WEP40:
150e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	case WLAN_CIPHER_SUITE_WEP104:
151e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	case WLAN_CIPHER_SUITE_TKIP:
152e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	case WLAN_CIPHER_SUITE_CCMP:
153e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	case WLAN_CIPHER_SUITE_AES_CMAC:
154e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg		/* all of these we can do in software */
155e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg		return 0;
156e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	default:
157e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg		return -EINVAL;
1583ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg	}
15911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg}
16011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
16111a843b7e16062389c53ba393c7913956e034eb2Johannes Bergstatic void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
16211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg{
163dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	struct ieee80211_sub_if_data *sdata;
164dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	struct ieee80211_sta *sta;
16511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	int ret;
16611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
1673b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	might_sleep();
1683b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
169db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	if (!key || !key->local->ops->set_key)
17011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		return;
17111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
172ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	assert_key_lock(key->local);
173ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg
174ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
17511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		return;
17611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
177dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	sta = get_sta_for_key(key);
178dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	sdata = key->sdata;
179dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg
1803bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
1813bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	      (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)))
1823bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar		increment_tailroom_need_count(sdata);
1833bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar
184dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
185dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg		sdata = container_of(sdata->bss,
186dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg				     struct ieee80211_sub_if_data,
187dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg				     u.ap);
18811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
18912375ef933fa8271396ed0c1e318cb1bd2e2689dJohannes Berg	ret = drv_set_key(key->local, DISABLE_KEY, sdata,
1902448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg			  sta, &key->conf);
19111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
19211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	if (ret)
1930fb9a9ec27718fbf7fa3153bc94becefb716ceebJoe Perches		wiphy_err(key->local->hw.wiphy,
1940fb9a9ec27718fbf7fa3153bc94becefb716ceebJoe Perches			  "failed to remove key (%d, %pM) from hardware (%d)\n",
1950fb9a9ec27718fbf7fa3153bc94becefb716ceebJoe Perches			  key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
19611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
1973b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
1983b96766f0e643f52ae19e134664df6730c737e87Johannes Berg}
1993b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
200e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Bergvoid ieee80211_key_removed(struct ieee80211_key_conf *key_conf)
201e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg{
202e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	struct ieee80211_key *key;
203e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg
204e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	key = container_of(key_conf, struct ieee80211_key, conf);
205e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg
206e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	might_sleep();
207e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	assert_key_lock(key->local);
208e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg
209e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
210e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg
211e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	/*
212e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	 * Flush TX path to avoid attempts to use this key
213e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	 * after this function returns. Until then, drivers
214e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	 * must be prepared to handle the key.
215e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	 */
216e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	synchronize_rcu();
217e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg}
218e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes BergEXPORT_SYMBOL_GPL(ieee80211_key_removed);
219e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg
2203b96766f0e643f52ae19e134664df6730c737e87Johannes Bergstatic void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
221f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg					int idx, bool uni, bool multi)
2223b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{
2233b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	struct ieee80211_key *key = NULL;
2243b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
225ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	assert_key_lock(sdata->local);
226ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg
2273b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	if (idx >= 0 && idx < NUM_DEFAULT_KEYS)
22840b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg		key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
2293b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
230f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg	if (uni)
231f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg		rcu_assign_pointer(sdata->default_unicast_key, key);
232f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg	if (multi)
233f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg		rcu_assign_pointer(sdata->default_multicast_key, key);
2343b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
235f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg	ieee80211_debugfs_key_update_default(sdata);
2363b96766f0e643f52ae19e134664df6730c737e87Johannes Berg}
2373b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
238f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Bergvoid ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx,
239f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg			       bool uni, bool multi)
2403b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{
241ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_lock(&sdata->local->key_mtx);
242f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg	__ieee80211_set_default_key(sdata, idx, uni, multi);
243ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_unlock(&sdata->local->key_mtx);
2443b96766f0e643f52ae19e134664df6730c737e87Johannes Berg}
2453b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2463cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinenstatic void
2473cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen__ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx)
2483cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen{
2493cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	struct ieee80211_key *key = NULL;
2503cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen
251ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	assert_key_lock(sdata->local);
252ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg
2533cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	if (idx >= NUM_DEFAULT_KEYS &&
2543cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	    idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
25540b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg		key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
2563cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen
2573cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	rcu_assign_pointer(sdata->default_mgmt_key, key);
2583cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen
259f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg	ieee80211_debugfs_key_update_default(sdata);
2603cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen}
2613cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen
2623cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinenvoid ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
2633cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen				    int idx)
2643cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen{
265ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_lock(&sdata->local->key_mtx);
2663cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	__ieee80211_set_default_mgmt_key(sdata, idx);
267ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_unlock(&sdata->local->key_mtx);
2683cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen}
2693cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen
2703b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2713b96766f0e643f52ae19e134664df6730c737e87Johannes Bergstatic void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
2723b96766f0e643f52ae19e134664df6730c737e87Johannes Berg				    struct sta_info *sta,
273e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg				    bool pairwise,
2743b96766f0e643f52ae19e134664df6730c737e87Johannes Berg				    struct ieee80211_key *old,
2753b96766f0e643f52ae19e134664df6730c737e87Johannes Berg				    struct ieee80211_key *new)
2763b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{
277f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg	int idx;
278f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg	bool defunikey, defmultikey, defmgmtkey;
2793b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2803b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	if (new)
2813b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		list_add(&new->list, &sdata->key_list);
2823b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
283e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	if (sta && pairwise) {
284e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg		rcu_assign_pointer(sta->ptk, new);
285e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	} else if (sta) {
286e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg		if (old)
287e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg			idx = old->conf.keyidx;
288e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg		else
289e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg			idx = new->conf.keyidx;
290e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg		rcu_assign_pointer(sta->gtk[idx], new);
2913b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	} else {
2923b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx);
2933b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2943b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		if (old)
2953b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			idx = old->conf.keyidx;
2963b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		else
2973b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			idx = new->conf.keyidx;
2983b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
29940b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg		defunikey = old &&
30040b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg			old == key_mtx_dereference(sdata->local,
30140b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg						sdata->default_unicast_key);
30240b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg		defmultikey = old &&
30340b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg			old == key_mtx_dereference(sdata->local,
30440b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg						sdata->default_multicast_key);
30540b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg		defmgmtkey = old &&
30640b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg			old == key_mtx_dereference(sdata->local,
30740b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg						sdata->default_mgmt_key);
3083b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
309f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg		if (defunikey && !new)
310f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg			__ieee80211_set_default_key(sdata, -1, true, false);
311f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg		if (defmultikey && !new)
312f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg			__ieee80211_set_default_key(sdata, -1, false, true);
3133cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		if (defmgmtkey && !new)
3143cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen			__ieee80211_set_default_mgmt_key(sdata, -1);
3153b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
3163b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		rcu_assign_pointer(sdata->keys[idx], new);
317f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg		if (defunikey && new)
318f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg			__ieee80211_set_default_key(sdata, new->conf.keyidx,
319f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg						    true, false);
320f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg		if (defmultikey && new)
321f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg			__ieee80211_set_default_key(sdata, new->conf.keyidx,
322f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg						    false, true);
3233cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		if (defmgmtkey && new)
3243cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen			__ieee80211_set_default_mgmt_key(sdata,
3253cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen							 new->conf.keyidx);
3263b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	}
3273b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
328b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg	if (old)
329b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg		list_del(&old->list);
33011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg}
33111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
33297359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Bergstruct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
333faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen					  const u8 *key_data,
334faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen					  size_t seq_len, const u8 *seq)
3351f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg{
3361f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg	struct ieee80211_key *key;
3371ac62ba7c985109868a18d959986425148481f47Ben Hutchings	int i, j, err;
3381f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg
3393cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS);
34011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
34111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL);
3421f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg	if (!key)
3431ac62ba7c985109868a18d959986425148481f47Ben Hutchings		return ERR_PTR(-ENOMEM);
34411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
34511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	/*
34611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	 * Default to software encryption; we'll later upload the
34711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	 * key to the hardware if possible.
34811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	 */
34911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	key->conf.flags = 0;
35011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	key->flags = 0;
35111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
35297359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg	key->conf.cipher = cipher;
35311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	key->conf.keyidx = idx;
35411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	key->conf.keylen = key_len;
35597359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg	switch (cipher) {
35697359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg	case WLAN_CIPHER_SUITE_WEP40:
35797359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg	case WLAN_CIPHER_SUITE_WEP104:
35876708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		key->conf.iv_len = WEP_IV_LEN;
35976708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		key->conf.icv_len = WEP_ICV_LEN;
36076708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		break;
36197359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg	case WLAN_CIPHER_SUITE_TKIP:
36276708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		key->conf.iv_len = TKIP_IV_LEN;
36376708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		key->conf.icv_len = TKIP_ICV_LEN;
3649f26a952210e44691f784b77bf1f83a500d63f58Jouni Malinen		if (seq) {
365faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen			for (i = 0; i < NUM_RX_DATA_QUEUES; i++) {
366faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen				key->u.tkip.rx[i].iv32 =
367faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen					get_unaligned_le32(&seq[2]);
368faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen				key->u.tkip.rx[i].iv16 =
369faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen					get_unaligned_le16(seq);
370faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen			}
371faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen		}
372523b02ea23b175dd3e46e3daf1bc9354376640a3Johannes Berg		spin_lock_init(&key->u.tkip.txlock);
37376708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		break;
37497359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg	case WLAN_CIPHER_SUITE_CCMP:
37576708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		key->conf.iv_len = CCMP_HDR_LEN;
37676708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		key->conf.icv_len = CCMP_MIC_LEN;
3779f26a952210e44691f784b77bf1f83a500d63f58Jouni Malinen		if (seq) {
3789190252c952a33efa1ceff4ef35188f8a27b81cbJouni Malinen			for (i = 0; i < NUM_RX_DATA_QUEUES + 1; i++)
379faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen				for (j = 0; j < CCMP_PN_LEN; j++)
380faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen					key->u.ccmp.rx_pn[i][j] =
381faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen						seq[CCMP_PN_LEN - j - 1];
382faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen		}
38311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		/*
38411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		 * Initialize AES key state here as an optimization so that
38511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		 * it does not need to be initialized for every packet.
38611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		 */
38711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data);
3881ac62ba7c985109868a18d959986425148481f47Ben Hutchings		if (IS_ERR(key->u.ccmp.tfm)) {
3891ac62ba7c985109868a18d959986425148481f47Ben Hutchings			err = PTR_ERR(key->u.ccmp.tfm);
3903b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			kfree(key);
3911f951a7f8ba05192291f781ef99a892697e47d62Petr Å tetiar			return ERR_PTR(err);
39211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		}
39360ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg		break;
39460ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg	case WLAN_CIPHER_SUITE_AES_CMAC:
39560ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg		key->conf.iv_len = 0;
39660ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg		key->conf.icv_len = sizeof(struct ieee80211_mmie);
39760ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg		if (seq)
39860ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg			for (j = 0; j < 6; j++)
39960ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg				key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1];
4003cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		/*
4013cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		 * Initialize AES key state here as an optimization so that
4023cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		 * it does not need to be initialized for every packet.
4033cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		 */
4043cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		key->u.aes_cmac.tfm =
4053cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen			ieee80211_aes_cmac_key_setup(key_data);
4061ac62ba7c985109868a18d959986425148481f47Ben Hutchings		if (IS_ERR(key->u.aes_cmac.tfm)) {
4071ac62ba7c985109868a18d959986425148481f47Ben Hutchings			err = PTR_ERR(key->u.aes_cmac.tfm);
4083cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen			kfree(key);
4091f951a7f8ba05192291f781ef99a892697e47d62Petr Å tetiar			return ERR_PTR(err);
4103cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		}
41160ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg		break;
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
419ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Bergstatic void __ieee80211_key_destroy(struct ieee80211_key *key)
420ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg{
421ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	if (!key)
422ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg		return;
423ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg
424d2460f4b2fa6dbdeec800414f9cf5b1fc8b71197Johannes Berg	/*
425d2460f4b2fa6dbdeec800414f9cf5b1fc8b71197Johannes Berg	 * Synchronize so the TX path can no longer be using
426d2460f4b2fa6dbdeec800414f9cf5b1fc8b71197Johannes Berg	 * this key before we free/remove it.
427d2460f4b2fa6dbdeec800414f9cf5b1fc8b71197Johannes Berg	 */
428d2460f4b2fa6dbdeec800414f9cf5b1fc8b71197Johannes Berg	synchronize_rcu();
429d2460f4b2fa6dbdeec800414f9cf5b1fc8b71197Johannes Berg
43032162a4dab0e6a4ca7f886a01173b5f9b80843beJouni Malinen	if (key->local)
43132162a4dab0e6a4ca7f886a01173b5f9b80843beJouni Malinen		ieee80211_key_disable_hw_accel(key);
432ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg
43397359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg	if (key->conf.cipher == WLAN_CIPHER_SUITE_CCMP)
434ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg		ieee80211_aes_key_free(key->u.ccmp.tfm);
43597359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg	if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC)
436ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg		ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
4373bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	if (key->local) {
43832162a4dab0e6a4ca7f886a01173b5f9b80843beJouni Malinen		ieee80211_debugfs_key_remove(key);
4393bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar		key->sdata->crypto_tx_tailroom_needed_cnt--;
4403bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	}
441ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg
442ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	kfree(key);
443ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg}
444ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg
4453ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Bergint ieee80211_key_link(struct ieee80211_key *key,
4463ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg		       struct ieee80211_sub_if_data *sdata,
4473ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg		       struct sta_info *sta)
448db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg{
449db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	struct ieee80211_key *old_key;
4503ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg	int idx, ret;
45167aa030c0dff6095128bcb4e8043b48360f32331Mariusz Kozlowski	bool pairwise;
452db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg
453db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	BUG_ON(!sdata);
454db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	BUG_ON(!key);
455db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg
45667aa030c0dff6095128bcb4e8043b48360f32331Mariusz Kozlowski	pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE;
457db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	idx = key->conf.keyidx;
458db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	key->local = sdata->local;
459db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	key->sdata = sdata;
460db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	key->sta = sta;
461db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg
46211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	if (sta) {
46311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		/*
46411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		 * some hardware cannot handle TKIP with QoS, so
46511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		 * we indicate whether QoS could be in use.
46611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		 */
46707346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg		if (test_sta_flags(sta, WLAN_STA_WME))
46811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg			key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA;
46911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	} else {
47005c914fe330fa8e1cc67870dc0d3809dfd96c107Johannes Berg		if (sdata->vif.type == NL80211_IFTYPE_STATION) {
47111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg			struct sta_info *ap;
47211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
4733b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			/*
474b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg			 * We're getting a sta pointer in, so must be under
475b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg			 * appropriate locking for sta_info_get().
4763b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			 */
477d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg
47811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg			/* same here, the AP could be using QoS */
479abe60632f311d515b082b450504ee24006023951Johannes Berg			ap = sta_info_get(key->sdata, key->sdata->u.mgd.bssid);
48011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg			if (ap) {
48107346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg				if (test_sta_flags(ap, WLAN_STA_WME))
48211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg					key->conf.flags |=
48311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg						IEEE80211_KEY_FLAG_WMM_STA;
48411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg			}
48511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		}
48611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	}
48711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
488ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_lock(&sdata->local->key_mtx);
4893b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
490e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	if (sta && pairwise)
49140b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg		old_key = key_mtx_dereference(sdata->local, sta->ptk);
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
499e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg	__ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
500ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	__ieee80211_key_destroy(old_key);
501d4e46a3d9869563c6210b01bb651c40cbe65da80Johannes Berg
502ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	ieee80211_debugfs_key_add(key);
503db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg
5043ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg	ret = ieee80211_key_enable_hw_accel(key);
505523d2f6982136d332c9b7dd00e9e16da1091f060Johannes Berg
506ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_unlock(&sdata->local->key_mtx);
5073ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg
5083ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg	return ret;
5091f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg}
5101f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg
5115c0c36412b2dc6b1e243c7e9115306fe286583b7Johannes Bergvoid __ieee80211_key_free(struct ieee80211_key *key)
5121f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg{
5135c0c36412b2dc6b1e243c7e9115306fe286583b7Johannes Berg	if (!key)
5145c0c36412b2dc6b1e243c7e9115306fe286583b7Johannes Berg		return;
5155c0c36412b2dc6b1e243c7e9115306fe286583b7Johannes Berg
5163b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	/*
5173b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	 * Replace key with nothingness if it was ever used.
5183b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	 */
5193a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg	if (key->sdata)
5203b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		__ieee80211_key_replace(key->sdata, key->sta,
521e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg				key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
522e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg				key, NULL);
523ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	__ieee80211_key_destroy(key);
5243b96766f0e643f52ae19e134664df6730c737e87Johannes Berg}
525d4e46a3d9869563c6210b01bb651c40cbe65da80Johannes Berg
52632162a4dab0e6a4ca7f886a01173b5f9b80843beJouni Malinenvoid ieee80211_key_free(struct ieee80211_local *local,
52732162a4dab0e6a4ca7f886a01173b5f9b80843beJouni Malinen			struct ieee80211_key *key)
5283b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{
529ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_lock(&local->key_mtx);
5303a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg	__ieee80211_key_free(key);
531ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_unlock(&local->key_mtx);
5323a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg}
5333a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg
534ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Bergvoid ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
5353a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg{
5363a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg	struct ieee80211_key *key;
53711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
5383a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg	ASSERT_RTNL();
53911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
5409607e6b66a0d25ca63b70d54a4283fa13d8f7c9dJohannes Berg	if (WARN_ON(!ieee80211_sdata_running(sdata)))
5413a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg		return;
54211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
543ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_lock(&sdata->local->key_mtx);
54411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
5453bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	sdata->crypto_tx_tailroom_needed_cnt = 0;
5463bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar
5473bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	list_for_each_entry(key, &sdata->key_list, list) {
5483bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar		increment_tailroom_need_count(sdata);
549ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg		ieee80211_key_enable_hw_accel(key);
5503bff1865186c6bb97855f0c13e3850543dce9cefYogesh Ashok Powar	}
5513b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
552ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_unlock(&sdata->local->key_mtx);
55311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg}
55411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
555830af02f24fbc087999b757b8eca51829c67fa6fJohannes Bergvoid ieee80211_iter_keys(struct ieee80211_hw *hw,
556830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg			 struct ieee80211_vif *vif,
557830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg			 void (*iter)(struct ieee80211_hw *hw,
558830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg				      struct ieee80211_vif *vif,
559830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg				      struct ieee80211_sta *sta,
560830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg				      struct ieee80211_key_conf *key,
561830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg				      void *data),
562830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg			 void *iter_data)
563830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg{
564830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg	struct ieee80211_local *local = hw_to_local(hw);
565830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg	struct ieee80211_key *key;
566830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg	struct ieee80211_sub_if_data *sdata;
567830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg
568830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg	ASSERT_RTNL();
569830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg
570830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg	mutex_lock(&local->key_mtx);
571830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg	if (vif) {
572830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg		sdata = vif_to_sdata(vif);
573830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg		list_for_each_entry(key, &sdata->key_list, list)
574830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg			iter(hw, &sdata->vif,
575830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg			     key->sta ? &key->sta->sta : NULL,
576830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg			     &key->conf, iter_data);
577830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg	} else {
578830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg		list_for_each_entry(sdata, &local->interfaces, list)
579830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg			list_for_each_entry(key, &sdata->key_list, list)
580830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg				iter(hw, &sdata->vif,
581830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg				     key->sta ? &key->sta->sta : NULL,
582830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg				     &key->conf, iter_data);
583830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg	}
584830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg	mutex_unlock(&local->key_mtx);
585830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg}
586830af02f24fbc087999b757b8eca51829c67fa6fJohannes BergEXPORT_SYMBOL(ieee80211_iter_keys);
587830af02f24fbc087999b757b8eca51829c67fa6fJohannes Berg
588ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Bergvoid ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)
58911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg{
59011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	struct ieee80211_key *key;
59111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
592ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	ASSERT_RTNL();
593db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg
594ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_lock(&sdata->local->key_mtx);
59511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
596ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	list_for_each_entry(key, &sdata->key_list, list)
597ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg		ieee80211_key_disable_hw_accel(key);
59811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
599ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_unlock(&sdata->local->key_mtx);
6003b96766f0e643f52ae19e134664df6730c737e87Johannes Berg}
60111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
6023b96766f0e643f52ae19e134664df6730c737e87Johannes Bergvoid ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
6033b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{
6043b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	struct ieee80211_key *key, *tmp;
605db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg
606ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_lock(&sdata->local->key_mtx);
6073b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
6083cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	ieee80211_debugfs_key_remove_mgmt_default(sdata);
6093b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
6103b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
6113a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg		__ieee80211_key_free(key);
6123b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
613f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg	ieee80211_debugfs_key_update_default(sdata);
614f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg
615ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg	mutex_unlock(&sdata->local->key_mtx);
61611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg}
617c68f4b892c241bdddeb6f1c1864ac26197229471Johannes Berg
618c68f4b892c241bdddeb6f1c1864ac26197229471Johannes Berg
619c68f4b892c241bdddeb6f1c1864ac26197229471Johannes Bergvoid ieee80211_gtk_rekey_notify(struct ieee80211_vif *vif, const u8 *bssid,
620c68f4b892c241bdddeb6f1c1864ac26197229471Johannes Berg				const u8 *replay_ctr, gfp_t gfp)
621c68f4b892c241bdddeb6f1c1864ac26197229471Johannes Berg{
622c68f4b892c241bdddeb6f1c1864ac26197229471Johannes Berg	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
623c68f4b892c241bdddeb6f1c1864ac26197229471Johannes Berg
624c68f4b892c241bdddeb6f1c1864ac26197229471Johannes Berg	trace_api_gtk_rekey_notify(sdata, bssid, replay_ctr);
625c68f4b892c241bdddeb6f1c1864ac26197229471Johannes Berg
626c68f4b892c241bdddeb6f1c1864ac26197229471Johannes Berg	cfg80211_gtk_rekey_notify(sdata->dev, bssid, replay_ctr, gfp);
627c68f4b892c241bdddeb6f1c1864ac26197229471Johannes Berg}
628c68f4b892c241bdddeb6f1c1864ac26197229471Johannes BergEXPORT_SYMBOL_GPL(ieee80211_gtk_rekey_notify);
629