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