key.c revision b5c34f662a3519d34f9634a14d8de638fdbe0ca3
11f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg/* 21f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg * Copyright 2002-2005, Instant802 Networks, Inc. 31f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg * Copyright 2005-2006, Devicescape Software, Inc. 41f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 53b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net> 61f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg * 71f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg * This program is free software; you can redistribute it and/or modify 81f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg * it under the terms of the GNU General Public License version 2 as 91f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg * published by the Free Software Foundation. 101f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg */ 111f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg 1211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg#include <linux/if_ether.h> 1311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg#include <linux/etherdevice.h> 1411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg#include <linux/list.h> 15d4e46a3d9869563c6210b01bb651c40cbe65da80Johannes Berg#include <linux/rcupdate.h> 16db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg#include <linux/rtnetlink.h> 175a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 181f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg#include <net/mac80211.h> 191f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg#include "ieee80211_i.h" 202448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg#include "driver-ops.h" 211f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg#include "debugfs_key.h" 221f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg#include "aes_ccm.h" 233cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen#include "aes_cmac.h" 241f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg 2511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 26dbbea6713d6096cd1c411cb453a6b71292c78b33Johannes Berg/** 27dbbea6713d6096cd1c411cb453a6b71292c78b33Johannes Berg * DOC: Key handling basics 2811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * 2911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * Key handling in mac80211 is done based on per-interface (sub_if_data) 3011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * keys and per-station keys. Since each station belongs to an interface, 3111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * each station key also belongs to that interface. 3211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * 33b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * Hardware acceleration is done on a best-effort basis for algorithms 34b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * that are implemented in software, for each key the hardware is asked 35b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * to enable that key for offloading but if it cannot do that the key is 36b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * simply kept for software encryption (unless it is for an algorithm 37b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * that isn't implemented in software). 38b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * There is currently no way of knowing whether a key is handled in SW 39b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * or HW except by looking into debugfs. 4011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * 41b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * All key management is internally protected by a mutex. Within all 42b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * other parts of mac80211, key references are, just as STA structure 43b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * references, protected by RCU. Note, however, that some things are 44b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * unprotected, namely the key->sta dereferences within the hardware 45b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * acceleration functions. This means that sta_info_destroy() must 46b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * remove the key which waits for an RCU grace period. 4711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg */ 4811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 4911a843b7e16062389c53ba393c7913956e034eb2Johannes Bergstatic const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 5011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 51ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Bergstatic void assert_key_lock(struct ieee80211_local *local) 523b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{ 5346a5ebaf02d69e26ee0f47a0b8d2d9bc619240d4Johannes Berg lockdep_assert_held(&local->key_mtx); 543b96766f0e643f52ae19e134664df6730c737e87Johannes Berg} 553b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 56dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Bergstatic struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key) 5711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg{ 5811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg if (key->sta) 59dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg return &key->sta->sta; 6011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 61dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg return NULL; 6211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg} 6311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 643ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Bergstatic int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) 6511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg{ 66dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg struct ieee80211_sub_if_data *sdata; 67dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg struct ieee80211_sta *sta; 6811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg int ret; 6911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 703b96766f0e643f52ae19e134664df6730c737e87Johannes Berg might_sleep(); 713b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 72e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg if (!key->local->ops->set_key) 733ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg goto out_unsupported; 7411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 75ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg assert_key_lock(key->local); 76ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg 77dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg sta = get_sta_for_key(key); 78dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg 79e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg /* 80e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg * If this is a per-STA GTK, check if it 81e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg * is supported; if not, return. 82e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg */ 83e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg if (sta && !(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE) && 84e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg !(key->local->hw.flags & IEEE80211_HW_SUPPORTS_PER_STA_GTK)) 85e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg goto out_unsupported; 86e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg 87dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg sdata = key->sdata; 8818890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { 8918890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa /* 9018890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa * The driver doesn't know anything about VLAN interfaces. 9118890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa * Hence, don't send GTKs for VLAN interfaces to the driver. 9218890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa */ 9318890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa if (!(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE)) 9418890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa goto out_unsupported; 95dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg sdata = container_of(sdata->bss, 96dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg struct ieee80211_sub_if_data, 97dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg u.ap); 9818890d4b89d8507ad09289f6f57a71591c7e9e83Helmut Schaa } 9911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 10012375ef933fa8271396ed0c1e318cb1bd2e2689dJohannes Berg ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf); 10111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 102e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg if (!ret) { 10311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; 104e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg return 0; 105e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg } 10611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 107e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg if (ret != -ENOSPC && ret != -EOPNOTSUPP) 1080fb9a9ec27718fbf7fa3153bc94becefb716ceebJoe Perches wiphy_err(key->local->hw.wiphy, 1090fb9a9ec27718fbf7fa3153bc94becefb716ceebJoe Perches "failed to set key (%d, %pM) to hardware (%d)\n", 1100fb9a9ec27718fbf7fa3153bc94becefb716ceebJoe Perches key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); 1113ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg 112e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg out_unsupported: 113e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg switch (key->conf.cipher) { 114e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg case WLAN_CIPHER_SUITE_WEP40: 115e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg case WLAN_CIPHER_SUITE_WEP104: 116e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg case WLAN_CIPHER_SUITE_TKIP: 117e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg case WLAN_CIPHER_SUITE_CCMP: 118e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg case WLAN_CIPHER_SUITE_AES_CMAC: 119e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg /* all of these we can do in software */ 120e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg return 0; 121e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg default: 122e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg return -EINVAL; 1233ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg } 12411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg} 12511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 12611a843b7e16062389c53ba393c7913956e034eb2Johannes Bergstatic void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) 12711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg{ 128dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg struct ieee80211_sub_if_data *sdata; 129dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg struct ieee80211_sta *sta; 13011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg int ret; 13111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 1323b96766f0e643f52ae19e134664df6730c737e87Johannes Berg might_sleep(); 1333b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 134db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg if (!key || !key->local->ops->set_key) 13511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg return; 13611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 137ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg assert_key_lock(key->local); 138ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg 139ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) 14011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg return; 14111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 142dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg sta = get_sta_for_key(key); 143dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg sdata = key->sdata; 144dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg 145dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 146dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg sdata = container_of(sdata->bss, 147dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg struct ieee80211_sub_if_data, 148dc822b5db479dc0178d5c04cbb656dad0b6564fbJohannes Berg u.ap); 14911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 15012375ef933fa8271396ed0c1e318cb1bd2e2689dJohannes Berg ret = drv_set_key(key->local, DISABLE_KEY, sdata, 1512448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg sta, &key->conf); 15211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 15311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg if (ret) 1540fb9a9ec27718fbf7fa3153bc94becefb716ceebJoe Perches wiphy_err(key->local->hw.wiphy, 1550fb9a9ec27718fbf7fa3153bc94becefb716ceebJoe Perches "failed to remove key (%d, %pM) from hardware (%d)\n", 1560fb9a9ec27718fbf7fa3153bc94becefb716ceebJoe Perches key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); 15711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 1583b96766f0e643f52ae19e134664df6730c737e87Johannes Berg key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; 1593b96766f0e643f52ae19e134664df6730c737e87Johannes Berg} 1603b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 161e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Bergvoid ieee80211_key_removed(struct ieee80211_key_conf *key_conf) 162e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg{ 163e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg struct ieee80211_key *key; 164e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg 165e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg key = container_of(key_conf, struct ieee80211_key, conf); 166e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg 167e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg might_sleep(); 168e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg assert_key_lock(key->local); 169e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg 170e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; 171e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg 172e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg /* 173e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg * Flush TX path to avoid attempts to use this key 174e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg * after this function returns. Until then, drivers 175e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg * must be prepared to handle the key. 176e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg */ 177e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg synchronize_rcu(); 178e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg} 179e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes BergEXPORT_SYMBOL_GPL(ieee80211_key_removed); 180e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg 1813b96766f0e643f52ae19e134664df6730c737e87Johannes Bergstatic void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, 182f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg int idx, bool uni, bool multi) 1833b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{ 1843b96766f0e643f52ae19e134664df6730c737e87Johannes Berg struct ieee80211_key *key = NULL; 1853b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 186ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg assert_key_lock(sdata->local); 187ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg 1883b96766f0e643f52ae19e134664df6730c737e87Johannes Berg if (idx >= 0 && idx < NUM_DEFAULT_KEYS) 1893b96766f0e643f52ae19e134664df6730c737e87Johannes Berg key = sdata->keys[idx]; 1903b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 191f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg if (uni) 192f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg rcu_assign_pointer(sdata->default_unicast_key, key); 193f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg if (multi) 194f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg rcu_assign_pointer(sdata->default_multicast_key, key); 1953b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 196f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg ieee80211_debugfs_key_update_default(sdata); 1973b96766f0e643f52ae19e134664df6730c737e87Johannes Berg} 1983b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 199f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Bergvoid ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx, 200f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg bool uni, bool multi) 2013b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{ 202ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg mutex_lock(&sdata->local->key_mtx); 203f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg __ieee80211_set_default_key(sdata, idx, uni, multi); 204ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg mutex_unlock(&sdata->local->key_mtx); 2053b96766f0e643f52ae19e134664df6730c737e87Johannes Berg} 2063b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 2073cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinenstatic void 2083cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen__ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx) 2093cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen{ 2103cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen struct ieee80211_key *key = NULL; 2113cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen 212ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg assert_key_lock(sdata->local); 213ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg 2143cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen if (idx >= NUM_DEFAULT_KEYS && 2153cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) 2163cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen key = sdata->keys[idx]; 2173cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen 2183cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen rcu_assign_pointer(sdata->default_mgmt_key, key); 2193cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen 220f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg ieee80211_debugfs_key_update_default(sdata); 2213cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen} 2223cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen 2233cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinenvoid ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, 2243cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen int idx) 2253cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen{ 226ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg mutex_lock(&sdata->local->key_mtx); 2273cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen __ieee80211_set_default_mgmt_key(sdata, idx); 228ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg mutex_unlock(&sdata->local->key_mtx); 2293cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen} 2303cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen 2313b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 2323b96766f0e643f52ae19e134664df6730c737e87Johannes Bergstatic void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, 2333b96766f0e643f52ae19e134664df6730c737e87Johannes Berg struct sta_info *sta, 234e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg bool pairwise, 2353b96766f0e643f52ae19e134664df6730c737e87Johannes Berg struct ieee80211_key *old, 2363b96766f0e643f52ae19e134664df6730c737e87Johannes Berg struct ieee80211_key *new) 2373b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{ 238f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg int idx; 239f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg bool defunikey, defmultikey, defmgmtkey; 2403b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 2413b96766f0e643f52ae19e134664df6730c737e87Johannes Berg if (new) 2423b96766f0e643f52ae19e134664df6730c737e87Johannes Berg list_add(&new->list, &sdata->key_list); 2433b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 244e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg if (sta && pairwise) { 245e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg rcu_assign_pointer(sta->ptk, new); 246e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg } else if (sta) { 247e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg if (old) 248e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg idx = old->conf.keyidx; 249e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg else 250e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg idx = new->conf.keyidx; 251e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg rcu_assign_pointer(sta->gtk[idx], new); 2523b96766f0e643f52ae19e134664df6730c737e87Johannes Berg } else { 2533b96766f0e643f52ae19e134664df6730c737e87Johannes Berg WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx); 2543b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 2553b96766f0e643f52ae19e134664df6730c737e87Johannes Berg if (old) 2563b96766f0e643f52ae19e134664df6730c737e87Johannes Berg idx = old->conf.keyidx; 2573b96766f0e643f52ae19e134664df6730c737e87Johannes Berg else 2583b96766f0e643f52ae19e134664df6730c737e87Johannes Berg idx = new->conf.keyidx; 2593b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 260f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg defunikey = old && sdata->default_unicast_key == old; 261f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg defmultikey = old && sdata->default_multicast_key == old; 2623cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen defmgmtkey = old && sdata->default_mgmt_key == old; 2633b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 264f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg if (defunikey && !new) 265f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg __ieee80211_set_default_key(sdata, -1, true, false); 266f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg if (defmultikey && !new) 267f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg __ieee80211_set_default_key(sdata, -1, false, true); 2683cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen if (defmgmtkey && !new) 2693cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen __ieee80211_set_default_mgmt_key(sdata, -1); 2703b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 2713b96766f0e643f52ae19e134664df6730c737e87Johannes Berg rcu_assign_pointer(sdata->keys[idx], new); 272f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg if (defunikey && new) 273f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg __ieee80211_set_default_key(sdata, new->conf.keyidx, 274f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg true, false); 275f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg if (defmultikey && new) 276f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg __ieee80211_set_default_key(sdata, new->conf.keyidx, 277f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg false, true); 2783cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen if (defmgmtkey && new) 2793cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen __ieee80211_set_default_mgmt_key(sdata, 2803cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen new->conf.keyidx); 2813b96766f0e643f52ae19e134664df6730c737e87Johannes Berg } 2823b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 283b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg if (old) 284b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg list_del(&old->list); 28511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg} 28611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 28797359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Bergstruct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, 288faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen const u8 *key_data, 289faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen size_t seq_len, const u8 *seq) 2901f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg{ 2911f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg struct ieee80211_key *key; 2921ac62ba7c985109868a18d959986425148481f47Ben Hutchings int i, j, err; 2931f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg 2943cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS); 29511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 29611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL); 2971f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg if (!key) 2981ac62ba7c985109868a18d959986425148481f47Ben Hutchings return ERR_PTR(-ENOMEM); 29911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 30011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg /* 30111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * Default to software encryption; we'll later upload the 30211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * key to the hardware if possible. 30311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg */ 30411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg key->conf.flags = 0; 30511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg key->flags = 0; 30611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 30797359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg key->conf.cipher = cipher; 30811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg key->conf.keyidx = idx; 30911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg key->conf.keylen = key_len; 31097359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg switch (cipher) { 31197359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg case WLAN_CIPHER_SUITE_WEP40: 31297359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg case WLAN_CIPHER_SUITE_WEP104: 31376708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau key->conf.iv_len = WEP_IV_LEN; 31476708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau key->conf.icv_len = WEP_ICV_LEN; 31576708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau break; 31697359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg case WLAN_CIPHER_SUITE_TKIP: 31776708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau key->conf.iv_len = TKIP_IV_LEN; 31876708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau key->conf.icv_len = TKIP_ICV_LEN; 3199f26a952210e44691f784b77bf1f83a500d63f58Jouni Malinen if (seq) { 320faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen for (i = 0; i < NUM_RX_DATA_QUEUES; i++) { 321faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen key->u.tkip.rx[i].iv32 = 322faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen get_unaligned_le32(&seq[2]); 323faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen key->u.tkip.rx[i].iv16 = 324faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen get_unaligned_le16(seq); 325faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen } 326faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen } 32776708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau break; 32897359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg case WLAN_CIPHER_SUITE_CCMP: 32976708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau key->conf.iv_len = CCMP_HDR_LEN; 33076708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau key->conf.icv_len = CCMP_MIC_LEN; 3319f26a952210e44691f784b77bf1f83a500d63f58Jouni Malinen if (seq) { 3329190252c952a33efa1ceff4ef35188f8a27b81cbJouni Malinen for (i = 0; i < NUM_RX_DATA_QUEUES + 1; i++) 333faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen for (j = 0; j < CCMP_PN_LEN; j++) 334faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen key->u.ccmp.rx_pn[i][j] = 335faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen seq[CCMP_PN_LEN - j - 1]; 336faa8fdc85347cc76d87b43ea718785661c54f656Jouni Malinen } 33711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg /* 33811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * Initialize AES key state here as an optimization so that 33911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * it does not need to be initialized for every packet. 34011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg */ 34111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data); 3421ac62ba7c985109868a18d959986425148481f47Ben Hutchings if (IS_ERR(key->u.ccmp.tfm)) { 3431ac62ba7c985109868a18d959986425148481f47Ben Hutchings err = PTR_ERR(key->u.ccmp.tfm); 3443b96766f0e643f52ae19e134664df6730c737e87Johannes Berg kfree(key); 3451ac62ba7c985109868a18d959986425148481f47Ben Hutchings key = ERR_PTR(err); 34611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg } 34760ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg break; 34860ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg case WLAN_CIPHER_SUITE_AES_CMAC: 34960ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg key->conf.iv_len = 0; 35060ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg key->conf.icv_len = sizeof(struct ieee80211_mmie); 35160ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg if (seq) 35260ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg for (j = 0; j < 6; j++) 35360ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1]; 3543cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen /* 3553cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen * Initialize AES key state here as an optimization so that 3563cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen * it does not need to be initialized for every packet. 3573cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen */ 3583cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen key->u.aes_cmac.tfm = 3593cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen ieee80211_aes_cmac_key_setup(key_data); 3601ac62ba7c985109868a18d959986425148481f47Ben Hutchings if (IS_ERR(key->u.aes_cmac.tfm)) { 3611ac62ba7c985109868a18d959986425148481f47Ben Hutchings err = PTR_ERR(key->u.aes_cmac.tfm); 3623cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen kfree(key); 3631ac62ba7c985109868a18d959986425148481f47Ben Hutchings key = ERR_PTR(err); 3643cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen } 36560ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg break; 3663cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen } 36760ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg memcpy(key->conf.key, key_data, key_len); 36860ae0f20058d19ada94093dc3ef7ae0737597fbaJohannes Berg INIT_LIST_HEAD(&key->list); 3693cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen 370db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg return key; 371db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg} 37211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 373ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Bergstatic void __ieee80211_key_destroy(struct ieee80211_key *key) 374ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg{ 375ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg if (!key) 376ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg return; 377ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg 37832162a4dab0e6a4ca7f886a01173b5f9b80843beJouni Malinen if (key->local) 37932162a4dab0e6a4ca7f886a01173b5f9b80843beJouni Malinen ieee80211_key_disable_hw_accel(key); 380ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg 38197359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg if (key->conf.cipher == WLAN_CIPHER_SUITE_CCMP) 382ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg ieee80211_aes_key_free(key->u.ccmp.tfm); 38397359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) 384ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); 38532162a4dab0e6a4ca7f886a01173b5f9b80843beJouni Malinen if (key->local) 38632162a4dab0e6a4ca7f886a01173b5f9b80843beJouni Malinen ieee80211_debugfs_key_remove(key); 387ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg 388ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg kfree(key); 389ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg} 390ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg 3913ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Bergint ieee80211_key_link(struct ieee80211_key *key, 3923ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg struct ieee80211_sub_if_data *sdata, 3933ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg struct sta_info *sta) 394db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg{ 395db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg struct ieee80211_key *old_key; 3963ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg int idx, ret; 397e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg bool pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE; 398db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg 399db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg BUG_ON(!sdata); 400db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg BUG_ON(!key); 401db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg 402db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg idx = key->conf.keyidx; 403db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg key->local = sdata->local; 404db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg key->sdata = sdata; 405db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg key->sta = sta; 406db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg 40711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg if (sta) { 40811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg /* 40911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * some hardware cannot handle TKIP with QoS, so 41011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg * we indicate whether QoS could be in use. 41111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg */ 41207346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg if (test_sta_flags(sta, WLAN_STA_WME)) 41311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA; 41411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg } else { 41505c914fe330fa8e1cc67870dc0d3809dfd96c107Johannes Berg if (sdata->vif.type == NL80211_IFTYPE_STATION) { 41611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg struct sta_info *ap; 41711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 4183b96766f0e643f52ae19e134664df6730c737e87Johannes Berg /* 419b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * We're getting a sta pointer in, so must be under 420b5c34f662a3519d34f9634a14d8de638fdbe0ca3Johannes Berg * appropriate locking for sta_info_get(). 4213b96766f0e643f52ae19e134664df6730c737e87Johannes Berg */ 422d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg 42311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg /* same here, the AP could be using QoS */ 424abe60632f311d515b082b450504ee24006023951Johannes Berg ap = sta_info_get(key->sdata, key->sdata->u.mgd.bssid); 42511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg if (ap) { 42607346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg if (test_sta_flags(ap, WLAN_STA_WME)) 42711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg key->conf.flags |= 42811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg IEEE80211_KEY_FLAG_WMM_STA; 42911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg } 43011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg } 43111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg } 43211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 433ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg mutex_lock(&sdata->local->key_mtx); 4343b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 435e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg if (sta && pairwise) 436e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg old_key = sta->ptk; 437e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg else if (sta) 438e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg old_key = sta->gtk[idx]; 439d4e46a3d9869563c6210b01bb651c40cbe65da80Johannes Berg else 440db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg old_key = sdata->keys[idx]; 441db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg 442e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg __ieee80211_key_replace(sdata, sta, pairwise, old_key, key); 443ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg __ieee80211_key_destroy(old_key); 444d4e46a3d9869563c6210b01bb651c40cbe65da80Johannes Berg 445ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg ieee80211_debugfs_key_add(key); 446db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg 4473ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg ret = ieee80211_key_enable_hw_accel(key); 448523d2f6982136d332c9b7dd00e9e16da1091f060Johannes Berg 449ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg mutex_unlock(&sdata->local->key_mtx); 4503ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg 4513ffc2a905b1faae4c0fe39d66f0752c3a4cbb3c7Johannes Berg return ret; 4521f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg} 4531f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg 4543a245766901a9dfdc3f53457a7954b369b50f281Johannes Bergstatic void __ieee80211_key_free(struct ieee80211_key *key) 4551f5a7e47ae58cc23c623c09f1c9d97b7a8cf6344Johannes Berg{ 4563b96766f0e643f52ae19e134664df6730c737e87Johannes Berg /* 4573b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * Replace key with nothingness if it was ever used. 4583b96766f0e643f52ae19e134664df6730c737e87Johannes Berg */ 4593a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg if (key->sdata) 4603b96766f0e643f52ae19e134664df6730c737e87Johannes Berg __ieee80211_key_replace(key->sdata, key->sta, 461e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, 462e31b82136d1adc7a599b6e99d3321e5831841f5aJohannes Berg key, NULL); 463ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg __ieee80211_key_destroy(key); 4643b96766f0e643f52ae19e134664df6730c737e87Johannes Berg} 465d4e46a3d9869563c6210b01bb651c40cbe65da80Johannes Berg 46632162a4dab0e6a4ca7f886a01173b5f9b80843beJouni Malinenvoid ieee80211_key_free(struct ieee80211_local *local, 46732162a4dab0e6a4ca7f886a01173b5f9b80843beJouni Malinen struct ieee80211_key *key) 4683b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{ 4693a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg if (!key) 4703b96766f0e643f52ae19e134664df6730c737e87Johannes Berg return; 4713b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 472ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg mutex_lock(&local->key_mtx); 4733a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg __ieee80211_key_free(key); 474ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg mutex_unlock(&local->key_mtx); 4753a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg} 4763a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg 477ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Bergvoid ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) 4783a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg{ 4793a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg struct ieee80211_key *key; 48011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 4813a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg ASSERT_RTNL(); 48211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 4839607e6b66a0d25ca63b70d54a4283fa13d8f7c9dJohannes Berg if (WARN_ON(!ieee80211_sdata_running(sdata))) 4843a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg return; 48511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 486ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg mutex_lock(&sdata->local->key_mtx); 48711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 488ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg list_for_each_entry(key, &sdata->key_list, list) 489ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg ieee80211_key_enable_hw_accel(key); 4903b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 491ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg mutex_unlock(&sdata->local->key_mtx); 49211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg} 49311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 494ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Bergvoid ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata) 49511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg{ 49611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg struct ieee80211_key *key; 49711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 498ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg ASSERT_RTNL(); 499db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg 500ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg mutex_lock(&sdata->local->key_mtx); 50111a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 502ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg list_for_each_entry(key, &sdata->key_list, list) 503ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg ieee80211_key_disable_hw_accel(key); 50411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 505ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg mutex_unlock(&sdata->local->key_mtx); 5063b96766f0e643f52ae19e134664df6730c737e87Johannes Berg} 50711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg 5083b96766f0e643f52ae19e134664df6730c737e87Johannes Bergvoid ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) 5093b96766f0e643f52ae19e134664df6730c737e87Johannes Berg{ 5103b96766f0e643f52ae19e134664df6730c737e87Johannes Berg struct ieee80211_key *key, *tmp; 511db4d1169d0b893bfb7923b6526748fe2c5a7373fJohannes Berg 512ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg mutex_lock(&sdata->local->key_mtx); 5133b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 5143cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen ieee80211_debugfs_key_remove_mgmt_default(sdata); 5153b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 5163b96766f0e643f52ae19e134664df6730c737e87Johannes Berg list_for_each_entry_safe(key, tmp, &sdata->key_list, list) 5173a245766901a9dfdc3f53457a7954b369b50f281Johannes Berg __ieee80211_key_free(key); 5183b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 519f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg ieee80211_debugfs_key_update_default(sdata); 520f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg 521ad0e2b5a00dbec303e4682b403bb6703d11dcdb2Johannes Berg mutex_unlock(&sdata->local->key_mtx); 52211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg} 523