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