key.c revision 9f26a952210e44691f784b77bf1f83a500d63f58
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>
171f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg#include <net/mac80211.h>
181f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg#include "ieee80211_i.h"
192448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg#include "driver-ops.h"
201f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg#include "debugfs_key.h"
211f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg#include "aes_ccm.h"
223cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen#include "aes_cmac.h"
231f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg
2411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
25dbbea6713d6096cd1c411cb453a6b71292c78b33Johannes Berg/**
26dbbea6713d6096cd1c411cb453a6b71292c78b33Johannes Berg * DOC: Key handling basics
2711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg *
2811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * Key handling in mac80211 is done based on per-interface (sub_if_data)
2911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * keys and per-station keys. Since each station belongs to an interface,
3011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * each station key also belongs to that interface.
3111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg *
3211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * Hardware acceleration is done on a best-effort basis, for each key
3311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * that is eligible the hardware is asked to enable that key but if
3411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * it cannot do that they key is simply kept for software encryption.
3511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * There is currently no way of knowing this except by looking into
3611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * debugfs.
3711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg *
383b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * All key operations are protected internally so you can call them at
393b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * any time.
40db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg *
413b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * Within mac80211, key references are, just as STA structure references,
423b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * protected by RCU. Note, however, that some things are unprotected,
433b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * namely the key->sta dereferences within the hardware acceleration
443b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * functions. This means that sta_info_destroy() must flush the key todo
453b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * list.
463b96766f0e643f52ae19e134664df6730c737e87Johannes Berg *
473b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * All the direct key list manipulation functions must not sleep because
483b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * they can operate on STA info structs that are protected by RCU.
4911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg */
5011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
5111a843b7e16062389c53ba393c7913956e034eb2Johannes Bergstatic const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
5211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
533b96766f0e643f52ae19e134664df6730c737e87Johannes Berg/* key mutex: used to synchronise todo runners */
543b96766f0e643f52ae19e134664df6730c737e87Johannes Bergstatic DEFINE_MUTEX(key_mutex);
553b96766f0e643f52ae19e134664df6730c737e87Johannes Bergstatic DEFINE_SPINLOCK(todo_lock);
563b96766f0e643f52ae19e134664df6730c737e87Johannes Bergstatic LIST_HEAD(todo_list);
573b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
583b96766f0e643f52ae19e134664df6730c737e87Johannes Bergstatic void key_todo(struct work_struct *work)
593b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{
603b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	ieee80211_key_todo();
613b96766f0e643f52ae19e134664df6730c737e87Johannes Berg}
623b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
633b96766f0e643f52ae19e134664df6730c737e87Johannes Bergstatic DECLARE_WORK(todo_work, key_todo);
643b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
653b96766f0e643f52ae19e134664df6730c737e87Johannes Berg/**
663b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * add_todo - add todo item for a key
673b96766f0e643f52ae19e134664df6730c737e87Johannes Berg *
683b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * @key: key to add to do item for
693b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * @flag: todo flag(s)
703b96766f0e643f52ae19e134664df6730c737e87Johannes Berg */
713b96766f0e643f52ae19e134664df6730c737e87Johannes Bergstatic void add_todo(struct ieee80211_key *key, u32 flag)
723b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{
733b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	if (!key)
743b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		return;
753b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
763b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	spin_lock(&todo_lock);
773b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	key->flags |= flag;
78245cbe7a65f3e17999de276ea1c84538f3a7451eJohannes Berg	/*
79245cbe7a65f3e17999de276ea1c84538f3a7451eJohannes Berg	 * Remove again if already on the list so that we move it to the end.
80245cbe7a65f3e17999de276ea1c84538f3a7451eJohannes Berg	 */
81245cbe7a65f3e17999de276ea1c84538f3a7451eJohannes Berg	if (!list_empty(&key->todo))
82245cbe7a65f3e17999de276ea1c84538f3a7451eJohannes Berg		list_del(&key->todo);
83245cbe7a65f3e17999de276ea1c84538f3a7451eJohannes Berg	list_add_tail(&key->todo, &todo_list);
843b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	schedule_work(&todo_work);
853b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	spin_unlock(&todo_lock);
863b96766f0e643f52ae19e134664df6730c737e87Johannes Berg}
873b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
883b96766f0e643f52ae19e134664df6730c737e87Johannes Berg/**
893b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * ieee80211_key_lock - lock the mac80211 key operation lock
903b96766f0e643f52ae19e134664df6730c737e87Johannes Berg *
913b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * This locks the (global) mac80211 key operation lock, all
923b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * key operations must be done under this lock.
933b96766f0e643f52ae19e134664df6730c737e87Johannes Berg */
943b96766f0e643f52ae19e134664df6730c737e87Johannes Bergstatic void ieee80211_key_lock(void)
953b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{
963b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	mutex_lock(&key_mutex);
973b96766f0e643f52ae19e134664df6730c737e87Johannes Berg}
983b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
993b96766f0e643f52ae19e134664df6730c737e87Johannes Berg/**
1003b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * ieee80211_key_unlock - unlock the mac80211 key operation lock
1013b96766f0e643f52ae19e134664df6730c737e87Johannes Berg */
1023b96766f0e643f52ae19e134664df6730c737e87Johannes Bergstatic void ieee80211_key_unlock(void)
1033b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{
1043b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	mutex_unlock(&key_mutex);
1053b96766f0e643f52ae19e134664df6730c737e87Johannes Berg}
1063b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
1073b96766f0e643f52ae19e134664df6730c737e87Johannes Bergstatic void assert_key_lock(void)
1083b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{
1093b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	WARN_ON(!mutex_is_locked(&key_mutex));
1103b96766f0e643f52ae19e134664df6730c737e87Johannes Berg}
1113b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
112dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Bergstatic struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key)
11311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg{
11411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	if (key->sta)
115dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg		return &key->sta->sta;
11611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
117dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	return NULL;
11811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg}
11911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
12011a843b7e16062389c53ba393c7913956e034eb2Johannes Bergstatic void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
12111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg{
122dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	struct ieee80211_sub_if_data *sdata;
123dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	struct ieee80211_sta *sta;
12411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	int ret;
12511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
1263b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	assert_key_lock();
1273b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	might_sleep();
1283b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
12911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	if (!key->local->ops->set_key)
13011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		return;
13111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
132dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	sta = get_sta_for_key(key);
133dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg
134dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	sdata = key->sdata;
135dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
136dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg		sdata = container_of(sdata->bss,
137dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg				     struct ieee80211_sub_if_data,
138dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg				     u.ap);
13911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
1402448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg	ret = drv_set_key(key->local, SET_KEY, &sdata->vif, sta, &key->conf);
14111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
1423b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	if (!ret) {
1433b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		spin_lock(&todo_lock);
14411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
1453b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		spin_unlock(&todo_lock);
1463b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	}
14711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
14811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP)
14911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		printk(KERN_ERR "mac80211-%s: failed to set key "
1500c68ae2605dbcf67414d8d1f19af93be44b355fbJohannes Berg		       "(%d, %pM) to hardware (%d)\n",
15111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		       wiphy_name(key->local->hw.wiphy),
152dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg		       key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
15311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg}
15411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
15511a843b7e16062389c53ba393c7913956e034eb2Johannes Bergstatic void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
15611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg{
157dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	struct ieee80211_sub_if_data *sdata;
158dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	struct ieee80211_sta *sta;
15911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	int ret;
16011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
1613b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	assert_key_lock();
1623b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	might_sleep();
1633b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
164db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	if (!key || !key->local->ops->set_key)
16511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		return;
16611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
1673b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	spin_lock(&todo_lock);
1683b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
1693b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		spin_unlock(&todo_lock);
17011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		return;
1713b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	}
1723b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	spin_unlock(&todo_lock);
17311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
174dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	sta = get_sta_for_key(key);
175dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	sdata = key->sdata;
176dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg
177dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
178dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg		sdata = container_of(sdata->bss,
179dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg				     struct ieee80211_sub_if_data,
180dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg				     u.ap);
18111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
1822448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg	ret = drv_set_key(key->local, DISABLE_KEY, &sdata->vif,
1832448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg			  sta, &key->conf);
18411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
18511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	if (ret)
18611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		printk(KERN_ERR "mac80211-%s: failed to remove key "
1870c68ae2605dbcf67414d8d1f19af93be44b355fbJohannes Berg		       "(%d, %pM) from hardware (%d)\n",
18811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		       wiphy_name(key->local->hw.wiphy),
189dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg		       key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
19011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
1913b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	spin_lock(&todo_lock);
1923b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
1933b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	spin_unlock(&todo_lock);
1943b96766f0e643f52ae19e134664df6730c737e87Johannes Berg}
1953b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
1963b96766f0e643f52ae19e134664df6730c737e87Johannes Bergstatic void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
1973b96766f0e643f52ae19e134664df6730c737e87Johannes Berg					int idx)
1983b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{
1993b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	struct ieee80211_key *key = NULL;
2003b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2013b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	if (idx >= 0 && idx < NUM_DEFAULT_KEYS)
2023b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		key = sdata->keys[idx];
2033b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2043b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	rcu_assign_pointer(sdata->default_key, key);
2053b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2063b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	if (key)
2073b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		add_todo(key, KEY_FLAG_TODO_DEFKEY);
2083b96766f0e643f52ae19e134664df6730c737e87Johannes Berg}
2093b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2103b96766f0e643f52ae19e134664df6730c737e87Johannes Bergvoid ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx)
2113b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{
2123b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	unsigned long flags;
2133b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
214b16bd15c379410f2aa47837aa4a0de5712856ad5Johannes Berg	spin_lock_irqsave(&sdata->local->key_lock, flags);
2153b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	__ieee80211_set_default_key(sdata, idx);
216b16bd15c379410f2aa47837aa4a0de5712856ad5Johannes Berg	spin_unlock_irqrestore(&sdata->local->key_lock, flags);
2173b96766f0e643f52ae19e134664df6730c737e87Johannes Berg}
2183b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2193cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinenstatic void
2203cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen__ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx)
2213cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen{
2223cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	struct ieee80211_key *key = NULL;
2233cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen
2243cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	if (idx >= NUM_DEFAULT_KEYS &&
2253cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	    idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
2263cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		key = sdata->keys[idx];
2273cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen
2283cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	rcu_assign_pointer(sdata->default_mgmt_key, key);
2293cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen
2303cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	if (key)
2313cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		add_todo(key, KEY_FLAG_TODO_DEFMGMTKEY);
2323cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen}
2333cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen
2343cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinenvoid ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
2353cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen				    int idx)
2363cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen{
2373cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	unsigned long flags;
2383cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen
2393cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	spin_lock_irqsave(&sdata->local->key_lock, flags);
2403cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	__ieee80211_set_default_mgmt_key(sdata, idx);
2413cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	spin_unlock_irqrestore(&sdata->local->key_lock, flags);
2423cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen}
2433cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen
2443b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2453b96766f0e643f52ae19e134664df6730c737e87Johannes Bergstatic void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
2463b96766f0e643f52ae19e134664df6730c737e87Johannes Berg				    struct sta_info *sta,
2473b96766f0e643f52ae19e134664df6730c737e87Johannes Berg				    struct ieee80211_key *old,
2483b96766f0e643f52ae19e134664df6730c737e87Johannes Berg				    struct ieee80211_key *new)
2493b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{
2503cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	int idx, defkey, defmgmtkey;
2513b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2523b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	if (new)
2533b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		list_add(&new->list, &sdata->key_list);
2543b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2553b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	if (sta) {
2563b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		rcu_assign_pointer(sta->key, new);
2573b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	} else {
2583b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx);
2593b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2603b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		if (old)
2613b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			idx = old->conf.keyidx;
2623b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		else
2633b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			idx = new->conf.keyidx;
2643b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2653b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		defkey = old && sdata->default_key == old;
2663cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		defmgmtkey = old && sdata->default_mgmt_key == old;
2673b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2683b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		if (defkey && !new)
2693b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			__ieee80211_set_default_key(sdata, -1);
2703cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		if (defmgmtkey && !new)
2713cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen			__ieee80211_set_default_mgmt_key(sdata, -1);
2723b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2733b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		rcu_assign_pointer(sdata->keys[idx], new);
2743b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		if (defkey && new)
2753b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			__ieee80211_set_default_key(sdata, new->conf.keyidx);
2763cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		if (defmgmtkey && new)
2773cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen			__ieee80211_set_default_mgmt_key(sdata,
2783cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen							 new->conf.keyidx);
2793b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	}
2803b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
2813b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	if (old) {
2823b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		/*
2833b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		 * We'll use an empty list to indicate that the key
2843b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		 * has already been removed.
2853b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		 */
2863b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		list_del_init(&old->list);
2873b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	}
28811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg}
28911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
290db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Bergstruct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
29111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg					  int idx,
29211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg					  size_t key_len,
293faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen					  const u8 *key_data,
294faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen					  size_t seq_len, const u8 *seq)
2951f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg{
2961f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg	struct ieee80211_key *key;
297faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen	int i, j;
2981f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg
2993cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS);
30011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
30111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL);
3021f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg	if (!key)
3031f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg		return NULL;
30411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
30511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	/*
30611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	 * Default to software encryption; we'll later upload the
30711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	 * key to the hardware if possible.
30811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	 */
30911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	key->conf.flags = 0;
31011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	key->flags = 0;
31111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
31211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	key->conf.alg = alg;
31311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	key->conf.keyidx = idx;
31411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	key->conf.keylen = key_len;
31576708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau	switch (alg) {
31676708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau	case ALG_WEP:
31776708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		key->conf.iv_len = WEP_IV_LEN;
31876708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		key->conf.icv_len = WEP_ICV_LEN;
31976708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		break;
32076708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau	case ALG_TKIP:
32176708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		key->conf.iv_len = TKIP_IV_LEN;
32276708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		key->conf.icv_len = TKIP_ICV_LEN;
3239f26a952210e44691f784b77bf1f83a500d63f58Jouni Malinen		if (seq) {
324faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen			for (i = 0; i < NUM_RX_DATA_QUEUES; i++) {
325faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen				key->u.tkip.rx[i].iv32 =
326faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen					get_unaligned_le32(&seq[2]);
327faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen				key->u.tkip.rx[i].iv16 =
328faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen					get_unaligned_le16(seq);
329faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen			}
330faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen		}
33176708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		break;
33276708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau	case ALG_CCMP:
33376708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		key->conf.iv_len = CCMP_HDR_LEN;
33476708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		key->conf.icv_len = CCMP_MIC_LEN;
3359f26a952210e44691f784b77bf1f83a500d63f58Jouni Malinen		if (seq) {
336faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen			for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
337faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen				for (j = 0; j < CCMP_PN_LEN; j++)
338faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen					key->u.ccmp.rx_pn[i][j] =
339faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen						seq[CCMP_PN_LEN - j - 1];
340faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen		}
34176708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		break;
3423cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	case ALG_AES_CMAC:
3433cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		key->conf.iv_len = 0;
3443cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		key->conf.icv_len = sizeof(struct ieee80211_mmie);
3459f26a952210e44691f784b77bf1f83a500d63f58Jouni Malinen		if (seq)
346faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen			for (j = 0; j < 6; j++)
347faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen				key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1];
3483cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		break;
34976708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau	}
35011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	memcpy(key->conf.key, key_data, key_len);
351e4861829072c61883114c64a3af61f305a789ff0Johannes Berg	INIT_LIST_HEAD(&key->list);
3523b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	INIT_LIST_HEAD(&key->todo);
35311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
35411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	if (alg == ALG_CCMP) {
35511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		/*
35611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		 * Initialize AES key state here as an optimization so that
35711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		 * it does not need to be initialized for every packet.
35811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		 */
35911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data);
36011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		if (!key->u.ccmp.tfm) {
3613b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			kfree(key);
36211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg			return NULL;
36311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		}
36411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	}
36511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
3663cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	if (alg == ALG_AES_CMAC) {
3673cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		/*
3683cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		 * Initialize AES key state here as an optimization so that
3693cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		 * it does not need to be initialized for every packet.
3703cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		 */
3713cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		key->u.aes_cmac.tfm =
3723cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen			ieee80211_aes_cmac_key_setup(key_data);
3733cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		if (!key->u.aes_cmac.tfm) {
3743cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen			kfree(key);
3753cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen			return NULL;
3763cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		}
3773cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	}
3783cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen
379db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	return key;
380db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg}
38111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
382db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Bergvoid ieee80211_key_link(struct ieee80211_key *key,
383db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg			struct ieee80211_sub_if_data *sdata,
384db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg			struct sta_info *sta)
385db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg{
386db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	struct ieee80211_key *old_key;
3873b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	unsigned long flags;
388db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	int idx;
389db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg
390db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	BUG_ON(!sdata);
391db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	BUG_ON(!key);
392db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg
393db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	idx = key->conf.keyidx;
394db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	key->local = sdata->local;
395db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	key->sdata = sdata;
396db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	key->sta = sta;
397db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg
39811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	if (sta) {
39911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		/*
40011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		 * some hardware cannot handle TKIP with QoS, so
40111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		 * we indicate whether QoS could be in use.
40211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		 */
40307346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg		if (test_sta_flags(sta, WLAN_STA_WME))
40411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg			key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA;
405c6adbd2158fee972adcc6232de5e2ef375f1f782Ivo van Doorn
406c6adbd2158fee972adcc6232de5e2ef375f1f782Ivo van Doorn		/*
407c6adbd2158fee972adcc6232de5e2ef375f1f782Ivo van Doorn		 * This key is for a specific sta interface,
408c6adbd2158fee972adcc6232de5e2ef375f1f782Ivo van Doorn		 * inform the driver that it should try to store
409c6adbd2158fee972adcc6232de5e2ef375f1f782Ivo van Doorn		 * this key as pairwise key.
410c6adbd2158fee972adcc6232de5e2ef375f1f782Ivo van Doorn		 */
411c6adbd2158fee972adcc6232de5e2ef375f1f782Ivo van Doorn		key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE;
41211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	} else {
41305c914fe330fa8e1cc67870dc0d3809dfd96c107Johannes Berg		if (sdata->vif.type == NL80211_IFTYPE_STATION) {
41411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg			struct sta_info *ap;
41511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
4163b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			/*
4173b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			 * We're getting a sta pointer in,
4183b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			 * so must be under RCU read lock.
4193b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			 */
420d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg
42111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg			/* same here, the AP could be using QoS */
422469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			ap = sta_info_get(key->local, key->sdata->u.mgd.bssid);
42311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg			if (ap) {
42407346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg				if (test_sta_flags(ap, WLAN_STA_WME))
42511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg					key->conf.flags |=
42611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg						IEEE80211_KEY_FLAG_WMM_STA;
42711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg			}
42811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		}
42911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	}
43011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
431b16bd15c379410f2aa47837aa4a0de5712856ad5Johannes Berg	spin_lock_irqsave(&sdata->local->key_lock, flags);
4323b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
433d4e46a3d9869563c6210b01bb651c40cbe65da80Johannes Berg	if (sta)
434db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg		old_key = sta->key;
435d4e46a3d9869563c6210b01bb651c40cbe65da80Johannes Berg	else
436db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg		old_key = sdata->keys[idx];
437db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg
438db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg	__ieee80211_key_replace(sdata, sta, old_key, key);
439d4e46a3d9869563c6210b01bb651c40cbe65da80Johannes Berg
440b16bd15c379410f2aa47837aa4a0de5712856ad5Johannes Berg	spin_unlock_irqrestore(&sdata->local->key_lock, flags);
4413b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
4423b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	/* free old key later */
4433b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	add_todo(old_key, KEY_FLAG_TODO_DELETE);
444db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg
4453b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS);
446e4861829072c61883114c64a3af61f305a789ff0Johannes Berg	if (netif_running(sdata->dev))
4473a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg		add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD);
4481f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg}
4491f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg
4503a245766901a9dfdc3f53457a7954b369b50f281Johannes Bergstatic void __ieee80211_key_free(struct ieee80211_key *key)
4511f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg{
4523b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	/*
4533b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	 * Replace key with nothingness if it was ever used.
4543b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	 */
4553a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg	if (key->sdata)
4563b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		__ieee80211_key_replace(key->sdata, key->sta,
4573b96766f0e643f52ae19e134664df6730c737e87Johannes Berg					key, NULL);
45811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
4593b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	add_todo(key, KEY_FLAG_TODO_DELETE);
4603b96766f0e643f52ae19e134664df6730c737e87Johannes Berg}
461d4e46a3d9869563c6210b01bb651c40cbe65da80Johannes Berg
4623a245766901a9dfdc3f53457a7954b369b50f281Johannes Bergvoid ieee80211_key_free(struct ieee80211_key *key)
4633b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{
4643a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg	unsigned long flags;
46511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
4663a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg	if (!key)
4673b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		return;
4683b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
46900eb7fe77eb455f807c396f9917f0f623d4c84bbEmmanuel Grumbach	if (!key->sdata) {
47000eb7fe77eb455f807c396f9917f0f623d4c84bbEmmanuel Grumbach		/* The key has not been linked yet, simply free it
47100eb7fe77eb455f807c396f9917f0f623d4c84bbEmmanuel Grumbach		 * and don't Oops */
47200eb7fe77eb455f807c396f9917f0f623d4c84bbEmmanuel Grumbach		if (key->conf.alg == ALG_CCMP)
47300eb7fe77eb455f807c396f9917f0f623d4c84bbEmmanuel Grumbach			ieee80211_aes_key_free(key->u.ccmp.tfm);
47400eb7fe77eb455f807c396f9917f0f623d4c84bbEmmanuel Grumbach		kfree(key);
47500eb7fe77eb455f807c396f9917f0f623d4c84bbEmmanuel Grumbach		return;
47600eb7fe77eb455f807c396f9917f0f623d4c84bbEmmanuel Grumbach	}
47700eb7fe77eb455f807c396f9917f0f623d4c84bbEmmanuel Grumbach
478b16bd15c379410f2aa47837aa4a0de5712856ad5Johannes Berg	spin_lock_irqsave(&key->sdata->local->key_lock, flags);
4793a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg	__ieee80211_key_free(key);
480b16bd15c379410f2aa47837aa4a0de5712856ad5Johannes Berg	spin_unlock_irqrestore(&key->sdata->local->key_lock, flags);
4813a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg}
4823a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg
4833a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg/*
4843a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg * To be safe against concurrent manipulations of the list (which shouldn't
4853a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg * actually happen) we need to hold the spinlock. But under the spinlock we
4863a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg * can't actually do much, so we defer processing to the todo list. Then run
4873a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg * the todo list to be sure the operation and possibly previously pending
4883a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg * operations are completed.
4893a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg */
4903a245766901a9dfdc3f53457a7954b369b50f281Johannes Bergstatic void ieee80211_todo_for_each_key(struct ieee80211_sub_if_data *sdata,
4913a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg					u32 todo_flags)
4923a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg{
4933a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg	struct ieee80211_key *key;
4943a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg	unsigned long flags;
4953b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
4963a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg	might_sleep();
4973a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg
498b16bd15c379410f2aa47837aa4a0de5712856ad5Johannes Berg	spin_lock_irqsave(&sdata->local->key_lock, flags);
4993b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	list_for_each_entry(key, &sdata->key_list, list)
5003a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg		add_todo(key, todo_flags);
501b16bd15c379410f2aa47837aa4a0de5712856ad5Johannes Berg	spin_unlock_irqrestore(&sdata->local->key_lock, flags);
5023b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
5033a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg	ieee80211_key_todo();
5041f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg}
50511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
5063a245766901a9dfdc3f53457a7954b369b50f281Johannes Bergvoid ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
50711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg{
5083a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg	ASSERT_RTNL();
50911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
5103a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg	if (WARN_ON(!netif_running(sdata->dev)))
5113a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg		return;
51211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
5133a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg	ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_ADD);
5143a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg}
51511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
5163a245766901a9dfdc3f53457a7954b369b50f281Johannes Bergvoid ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)
5173a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg{
5183a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg	ASSERT_RTNL();
51911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
5203a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg	ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_REMOVE);
52111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg}
52211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
5233a245766901a9dfdc3f53457a7954b369b50f281Johannes Bergstatic void __ieee80211_key_destroy(struct ieee80211_key *key)
52411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg{
5253b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	if (!key)
5263b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		return;
527db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg
5283b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	ieee80211_key_disable_hw_accel(key);
52911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
5303b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	if (key->conf.alg == ALG_CCMP)
5313b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		ieee80211_aes_key_free(key->u.ccmp.tfm);
5323cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	if (key->conf.alg == ALG_AES_CMAC)
5333cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
5343b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	ieee80211_debugfs_key_remove(key);
5353b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
5363b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	kfree(key);
53711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg}
53811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
5393b96766f0e643f52ae19e134664df6730c737e87Johannes Bergstatic void __ieee80211_key_todo(void)
54011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg{
54111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	struct ieee80211_key *key;
5423b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	bool work_done;
5433b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	u32 todoflags;
54411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
5453b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	/*
5463b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	 * NB: sta_info_destroy relies on this!
5473b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	 */
5483b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	synchronize_rcu();
5493b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
5503b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	spin_lock(&todo_lock);
5513b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	while (!list_empty(&todo_list)) {
5523b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		key = list_first_entry(&todo_list, struct ieee80211_key, todo);
5533b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		list_del_init(&key->todo);
5543b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		todoflags = key->flags & (KEY_FLAG_TODO_ADD_DEBUGFS |
5553b96766f0e643f52ae19e134664df6730c737e87Johannes Berg					  KEY_FLAG_TODO_DEFKEY |
5563cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen					  KEY_FLAG_TODO_DEFMGMTKEY |
5573a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg					  KEY_FLAG_TODO_HWACCEL_ADD |
5583a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg					  KEY_FLAG_TODO_HWACCEL_REMOVE |
5593b96766f0e643f52ae19e134664df6730c737e87Johannes Berg					  KEY_FLAG_TODO_DELETE);
5603b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		key->flags &= ~todoflags;
5613b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		spin_unlock(&todo_lock);
5623b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
5633b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		work_done = false;
5643b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
5653b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		if (todoflags & KEY_FLAG_TODO_ADD_DEBUGFS) {
5663b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			ieee80211_debugfs_key_add(key);
5673b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			work_done = true;
5683b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		}
5693b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		if (todoflags & KEY_FLAG_TODO_DEFKEY) {
5703b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			ieee80211_debugfs_key_remove_default(key->sdata);
5713b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			ieee80211_debugfs_key_add_default(key->sdata);
5723b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			work_done = true;
5733b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		}
5743cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		if (todoflags & KEY_FLAG_TODO_DEFMGMTKEY) {
5753cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen			ieee80211_debugfs_key_remove_mgmt_default(key->sdata);
5763cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen			ieee80211_debugfs_key_add_mgmt_default(key->sdata);
5773cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen			work_done = true;
5783cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen		}
5793a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg		if (todoflags & KEY_FLAG_TODO_HWACCEL_ADD) {
5803b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			ieee80211_key_enable_hw_accel(key);
5813b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			work_done = true;
5823b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		}
5833a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg		if (todoflags & KEY_FLAG_TODO_HWACCEL_REMOVE) {
5843a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg			ieee80211_key_disable_hw_accel(key);
5853a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg			work_done = true;
5863a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg		}
5873b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		if (todoflags & KEY_FLAG_TODO_DELETE) {
5883a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg			__ieee80211_key_destroy(key);
5893b96766f0e643f52ae19e134664df6730c737e87Johannes Berg			work_done = true;
5903b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		}
591db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg
5923b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		WARN_ON(!work_done);
59311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
5943b96766f0e643f52ae19e134664df6730c737e87Johannes Berg		spin_lock(&todo_lock);
5953b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	}
5963b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	spin_unlock(&todo_lock);
59711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg}
59811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
5993b96766f0e643f52ae19e134664df6730c737e87Johannes Bergvoid ieee80211_key_todo(void)
60011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg{
6013b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	ieee80211_key_lock();
6023b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	__ieee80211_key_todo();
6033b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	ieee80211_key_unlock();
6043b96766f0e643f52ae19e134664df6730c737e87Johannes Berg}
60511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg
6063b96766f0e643f52ae19e134664df6730c737e87Johannes Bergvoid ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
6073b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{
6083b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	struct ieee80211_key *key, *tmp;
6093a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg	unsigned long flags;
610db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg
6113b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	ieee80211_key_lock();
6123b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
6133b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	ieee80211_debugfs_key_remove_default(sdata);
6143cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen	ieee80211_debugfs_key_remove_mgmt_default(sdata);
6153b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
616b16bd15c379410f2aa47837aa4a0de5712856ad5Johannes Berg	spin_lock_irqsave(&sdata->local->key_lock, flags);
6173b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
6183a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg		__ieee80211_key_free(key);
619b16bd15c379410f2aa47837aa4a0de5712856ad5Johannes Berg	spin_unlock_irqrestore(&sdata->local->key_lock, flags);
6203b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
6213b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	__ieee80211_key_todo();
6223b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
6233b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	ieee80211_key_unlock();
62411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg}
625