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