Blame view
net/mac80211/key.c
30.1 KB
1f5a7e47a [MAC80211]: split... |
1 2 3 4 |
/* * Copyright 2002-2005, Instant802 Networks, Inc. * Copyright 2005-2006, Devicescape Software, Inc. * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
3b96766f0 mac80211: fix key... |
5 |
* Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net> |
d98ad83ee mac80211: add Int... |
6 |
* Copyright 2013-2014 Intel Mobile Communications GmbH |
1f5a7e47a [MAC80211]: split... |
7 8 9 10 11 |
* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ |
11a843b7e [MAC80211]: rewor... |
12 13 14 |
#include <linux/if_ether.h> #include <linux/etherdevice.h> #include <linux/list.h> |
d4e46a3d9 [MAC80211]: fix r... |
15 |
#include <linux/rcupdate.h> |
db4d1169d mac80211: split i... |
16 |
#include <linux/rtnetlink.h> |
5a0e3ad6a include cleanup: ... |
17 |
#include <linux/slab.h> |
bc3b2d7fb net: Add export.h... |
18 |
#include <linux/export.h> |
1f5a7e47a [MAC80211]: split... |
19 |
#include <net/mac80211.h> |
d26ad3771 mac80211: clean u... |
20 |
#include <asm/unaligned.h> |
1f5a7e47a [MAC80211]: split... |
21 |
#include "ieee80211_i.h" |
244879813 mac80211: add dri... |
22 |
#include "driver-ops.h" |
1f5a7e47a [MAC80211]: split... |
23 24 |
#include "debugfs_key.h" #include "aes_ccm.h" |
3cfcf6ac6 mac80211: 802.11w... |
25 |
#include "aes_cmac.h" |
8ade538bf mac80111: Add BIP... |
26 |
#include "aes_gmac.h" |
00b9cfa3f mac80111: Add GCM... |
27 |
#include "aes_gcm.h" |
1f5a7e47a [MAC80211]: split... |
28 |
|
11a843b7e [MAC80211]: rewor... |
29 |
|
dbbea6713 mac80211: add doc... |
30 31 |
/** * DOC: Key handling basics |
11a843b7e [MAC80211]: rewor... |
32 33 34 35 36 |
* * Key handling in mac80211 is done based on per-interface (sub_if_data) * keys and per-station keys. Since each station belongs to an interface, * each station key also belongs to that interface. * |
b5c34f662 mac80211: fix som... |
37 38 39 40 41 42 43 |
* Hardware acceleration is done on a best-effort basis for algorithms * that are implemented in software, for each key the hardware is asked * to enable that key for offloading but if it cannot do that the key is * simply kept for software encryption (unless it is for an algorithm * that isn't implemented in software). * There is currently no way of knowing whether a key is handled in SW * or HW except by looking into debugfs. |
11a843b7e [MAC80211]: rewor... |
44 |
* |
b5c34f662 mac80211: fix som... |
45 46 47 48 49 50 |
* All key management is internally protected by a mutex. Within all * other parts of mac80211, key references are, just as STA structure * references, protected by RCU. Note, however, that some things are * unprotected, namely the key->sta dereferences within the hardware * acceleration functions. This means that sta_info_destroy() must * remove the key which waits for an RCU grace period. |
11a843b7e [MAC80211]: rewor... |
51 52 53 |
*/ static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; |
11a843b7e [MAC80211]: rewor... |
54 |
|
ad0e2b5a0 mac80211: simplif... |
55 |
static void assert_key_lock(struct ieee80211_local *local) |
3b96766f0 mac80211: fix key... |
56 |
{ |
46a5ebaf0 cfg80211/mac80211... |
57 |
lockdep_assert_held(&local->key_mtx); |
3b96766f0 mac80211: fix key... |
58 |
} |
3bff18651 mac80211: Skip ta... |
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata) { /* * When this count is zero, SKB resizing for allocating tailroom * for IV or MMIC is skipped. But, this check has created two race * cases in xmit path while transiting from zero count to one: * * 1. SKB resize was skipped because no key was added but just before * the xmit key is added and SW encryption kicks off. * * 2. SKB resize was skipped because all the keys were hw planted but * just before xmit one of the key is deleted and SW encryption kicks * off. * * In both the above case SW encryption will find not enough space for * tailroom and exits with WARN_ON. (See WARN_ONs at wpa.c) * * Solution has been explained at * http://mid.gmane.org/1308590980.4322.19.camel@jlt3.sipsolutions.net */ if (!sdata->crypto_tx_tailroom_needed_cnt++) { /* * Flush all XMIT packets currently using HW encryption or no * encryption at all if the count transition is from 0 -> 1. */ synchronize_net(); } } |
3ffc2a905 mac80211: allow v... |
88 |
static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) |
11a843b7e [MAC80211]: rewor... |
89 |
{ |
dc822b5db mac80211: clean u... |
90 |
struct ieee80211_sub_if_data *sdata; |
89c91caec mac80211: dont pr... |
91 |
struct sta_info *sta; |
fa7e1fbcb mac80211: allow d... |
92 |
int ret = -EOPNOTSUPP; |
11a843b7e [MAC80211]: rewor... |
93 |
|
3b96766f0 mac80211: fix key... |
94 |
might_sleep(); |
4619194a4 mac80211: don't r... |
95 96 97 98 99 100 101 102 103 |
if (key->flags & KEY_FLAG_TAINTED) { /* If we get here, it's during resume and the key is * tainted so shouldn't be used/programmed any more. * However, its flags may still indicate that it was * programmed into the device (since we're in resume) * so clear that flag now to avoid trying to remove * it again later. */ key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; |
27b3eb9c0 mac80211: add API... |
104 |
return -EINVAL; |
4619194a4 mac80211: don't r... |
105 |
} |
27b3eb9c0 mac80211: add API... |
106 |
|
e31b82136 cfg80211/mac80211... |
107 |
if (!key->local->ops->set_key) |
3ffc2a905 mac80211: allow v... |
108 |
goto out_unsupported; |
11a843b7e [MAC80211]: rewor... |
109 |
|
ad0e2b5a0 mac80211: simplif... |
110 |
assert_key_lock(key->local); |
89c91caec mac80211: dont pr... |
111 |
sta = key->sta; |
dc822b5db mac80211: clean u... |
112 |
|
e31b82136 cfg80211/mac80211... |
113 114 115 116 117 118 119 |
/* * If this is a per-STA GTK, check if it * is supported; if not, return. */ if (sta && !(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE) && !(key->local->hw.flags & IEEE80211_HW_SUPPORTS_PER_STA_GTK)) goto out_unsupported; |
89c91caec mac80211: dont pr... |
120 121 |
if (sta && !sta->uploaded) goto out_unsupported; |
dc822b5db mac80211: clean u... |
122 |
sdata = key->sdata; |
18890d4b8 mac80211: Disable... |
123 124 125 126 127 128 129 |
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { /* * The driver doesn't know anything about VLAN interfaces. * Hence, don't send GTKs for VLAN interfaces to the driver. */ if (!(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE)) goto out_unsupported; |
18890d4b8 mac80211: Disable... |
130 |
} |
11a843b7e [MAC80211]: rewor... |
131 |
|
89c91caec mac80211: dont pr... |
132 133 |
ret = drv_set_key(key->local, SET_KEY, sdata, sta ? &sta->sta : NULL, &key->conf); |
11a843b7e [MAC80211]: rewor... |
134 |
|
e31b82136 cfg80211/mac80211... |
135 |
if (!ret) { |
11a843b7e [MAC80211]: rewor... |
136 |
key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; |
3bff18651 mac80211: Skip ta... |
137 |
|
1e359a5de Revert "mac80211:... |
138 |
if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || |
db12847ca mac80211: Re-fix ... |
139 |
(key->conf.flags & IEEE80211_KEY_FLAG_RESERVE_TAILROOM))) |
3bff18651 mac80211: Skip ta... |
140 |
sdata->crypto_tx_tailroom_needed_cnt--; |
077a91548 mac80211: support... |
141 142 |
WARN_ON((key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE) && (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)); |
e31b82136 cfg80211/mac80211... |
143 144 |
return 0; } |
11a843b7e [MAC80211]: rewor... |
145 |
|
fa7e1fbcb mac80211: allow d... |
146 |
if (ret != -ENOSPC && ret != -EOPNOTSUPP && ret != 1) |
bdcbd8e0e mac80211: clean u... |
147 |
sdata_err(sdata, |
0fb9a9ec2 net/mac80211: Use... |
148 149 |
"failed to set key (%d, %pM) to hardware (%d) ", |
89c91caec mac80211: dont pr... |
150 151 |
key->conf.keyidx, sta ? sta->sta.addr : bcast_addr, ret); |
3ffc2a905 mac80211: allow v... |
152 |
|
e31b82136 cfg80211/mac80211... |
153 154 155 156 157 158 |
out_unsupported: switch (key->conf.cipher) { case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: case WLAN_CIPHER_SUITE_TKIP: case WLAN_CIPHER_SUITE_CCMP: |
2b2ba0db1 mac80111: Add CCM... |
159 |
case WLAN_CIPHER_SUITE_CCMP_256: |
e31b82136 cfg80211/mac80211... |
160 |
case WLAN_CIPHER_SUITE_AES_CMAC: |
56c52da2d mac80111: Add BIP... |
161 |
case WLAN_CIPHER_SUITE_BIP_CMAC_256: |
8ade538bf mac80111: Add BIP... |
162 163 |
case WLAN_CIPHER_SUITE_BIP_GMAC_128: case WLAN_CIPHER_SUITE_BIP_GMAC_256: |
00b9cfa3f mac80111: Add GCM... |
164 165 |
case WLAN_CIPHER_SUITE_GCMP: case WLAN_CIPHER_SUITE_GCMP_256: |
fa7e1fbcb mac80211: allow d... |
166 167 168 169 170 |
/* all of these we can do in software - if driver can */ if (ret == 1) return 0; if (key->local->hw.flags & IEEE80211_HW_SW_CRYPTO_CONTROL) return -EINVAL; |
e31b82136 cfg80211/mac80211... |
171 172 173 |
return 0; default: return -EINVAL; |
3ffc2a905 mac80211: allow v... |
174 |
} |
11a843b7e [MAC80211]: rewor... |
175 176 177 178 |
} static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) { |
dc822b5db mac80211: clean u... |
179 |
struct ieee80211_sub_if_data *sdata; |
89c91caec mac80211: dont pr... |
180 |
struct sta_info *sta; |
11a843b7e [MAC80211]: rewor... |
181 |
int ret; |
3b96766f0 mac80211: fix key... |
182 |
might_sleep(); |
db4d1169d mac80211: split i... |
183 |
if (!key || !key->local->ops->set_key) |
11a843b7e [MAC80211]: rewor... |
184 |
return; |
ad0e2b5a0 mac80211: simplif... |
185 186 187 |
assert_key_lock(key->local); if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) |
11a843b7e [MAC80211]: rewor... |
188 |
return; |
89c91caec mac80211: dont pr... |
189 |
sta = key->sta; |
dc822b5db mac80211: clean u... |
190 |
sdata = key->sdata; |
1e359a5de Revert "mac80211:... |
191 |
if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || |
db12847ca mac80211: Re-fix ... |
192 |
(key->conf.flags & IEEE80211_KEY_FLAG_RESERVE_TAILROOM))) |
3bff18651 mac80211: Skip ta... |
193 |
increment_tailroom_need_count(sdata); |
12375ef93 mac80211: trace i... |
194 |
ret = drv_set_key(key->local, DISABLE_KEY, sdata, |
89c91caec mac80211: dont pr... |
195 |
sta ? &sta->sta : NULL, &key->conf); |
11a843b7e [MAC80211]: rewor... |
196 197 |
if (ret) |
bdcbd8e0e mac80211: clean u... |
198 |
sdata_err(sdata, |
0fb9a9ec2 net/mac80211: Use... |
199 200 |
"failed to remove key (%d, %pM) from hardware (%d) ", |
89c91caec mac80211: dont pr... |
201 202 |
key->conf.keyidx, sta ? sta->sta.addr : bcast_addr, ret); |
11a843b7e [MAC80211]: rewor... |
203 |
|
3b96766f0 mac80211: fix key... |
204 |
key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; |
3b96766f0 mac80211: fix key... |
205 206 207 |
} static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, |
f7e0104c1 mac80211: support... |
208 |
int idx, bool uni, bool multi) |
3b96766f0 mac80211: fix key... |
209 210 |
{ struct ieee80211_key *key = NULL; |
ad0e2b5a0 mac80211: simplif... |
211 |
assert_key_lock(sdata->local); |
3b96766f0 mac80211: fix key... |
212 |
if (idx >= 0 && idx < NUM_DEFAULT_KEYS) |
40b275b69 mac80211: sparse ... |
213 |
key = key_mtx_dereference(sdata->local, sdata->keys[idx]); |
3b96766f0 mac80211: fix key... |
214 |
|
de5fad815 mac80211: add op ... |
215 |
if (uni) { |
f7e0104c1 mac80211: support... |
216 |
rcu_assign_pointer(sdata->default_unicast_key, key); |
de5fad815 mac80211: add op ... |
217 218 |
drv_set_default_unicast_key(sdata->local, sdata, idx); } |
f7e0104c1 mac80211: support... |
219 220 |
if (multi) rcu_assign_pointer(sdata->default_multicast_key, key); |
3b96766f0 mac80211: fix key... |
221 |
|
f7e0104c1 mac80211: support... |
222 |
ieee80211_debugfs_key_update_default(sdata); |
3b96766f0 mac80211: fix key... |
223 |
} |
f7e0104c1 mac80211: support... |
224 225 |
void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx, bool uni, bool multi) |
3b96766f0 mac80211: fix key... |
226 |
{ |
ad0e2b5a0 mac80211: simplif... |
227 |
mutex_lock(&sdata->local->key_mtx); |
f7e0104c1 mac80211: support... |
228 |
__ieee80211_set_default_key(sdata, idx, uni, multi); |
ad0e2b5a0 mac80211: simplif... |
229 |
mutex_unlock(&sdata->local->key_mtx); |
3b96766f0 mac80211: fix key... |
230 |
} |
3cfcf6ac6 mac80211: 802.11w... |
231 232 233 234 |
static void __ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx) { struct ieee80211_key *key = NULL; |
ad0e2b5a0 mac80211: simplif... |
235 |
assert_key_lock(sdata->local); |
3cfcf6ac6 mac80211: 802.11w... |
236 237 |
if (idx >= NUM_DEFAULT_KEYS && idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) |
40b275b69 mac80211: sparse ... |
238 |
key = key_mtx_dereference(sdata->local, sdata->keys[idx]); |
3cfcf6ac6 mac80211: 802.11w... |
239 240 |
rcu_assign_pointer(sdata->default_mgmt_key, key); |
f7e0104c1 mac80211: support... |
241 |
ieee80211_debugfs_key_update_default(sdata); |
3cfcf6ac6 mac80211: 802.11w... |
242 243 244 245 246 |
} void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx) { |
ad0e2b5a0 mac80211: simplif... |
247 |
mutex_lock(&sdata->local->key_mtx); |
3cfcf6ac6 mac80211: 802.11w... |
248 |
__ieee80211_set_default_mgmt_key(sdata, idx); |
ad0e2b5a0 mac80211: simplif... |
249 |
mutex_unlock(&sdata->local->key_mtx); |
3cfcf6ac6 mac80211: 802.11w... |
250 |
} |
3b96766f0 mac80211: fix key... |
251 |
|
3b8d9c290 mac80211: remove ... |
252 253 254 255 256 |
static void ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, struct sta_info *sta, bool pairwise, struct ieee80211_key *old, struct ieee80211_key *new) |
3b96766f0 mac80211: fix key... |
257 |
{ |
f7e0104c1 mac80211: support... |
258 259 |
int idx; bool defunikey, defmultikey, defmgmtkey; |
3b96766f0 mac80211: fix key... |
260 |
|
5282c3ba4 mac80211: verify ... |
261 262 263 |
/* caller must provide at least one old/new */ if (WARN_ON(!new && !old)) return; |
3b96766f0 mac80211: fix key... |
264 |
if (new) |
f850e00fc mac80211: let key... |
265 |
list_add_tail(&new->list, &sdata->key_list); |
3b96766f0 mac80211: fix key... |
266 |
|
2475b1cc0 mac80211: add gen... |
267 |
WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx); |
3b96766f0 mac80211: fix key... |
268 |
|
2475b1cc0 mac80211: add gen... |
269 270 271 272 |
if (old) idx = old->conf.keyidx; else idx = new->conf.keyidx; |
3b96766f0 mac80211: fix key... |
273 |
|
2475b1cc0 mac80211: add gen... |
274 275 276 277 278 279 280 281 282 |
if (sta) { if (pairwise) { rcu_assign_pointer(sta->ptk[idx], new); sta->ptk_idx = idx; } else { rcu_assign_pointer(sta->gtk[idx], new); sta->gtk_idx = idx; } } else { |
40b275b69 mac80211: sparse ... |
283 284 285 286 287 288 289 290 291 |
defunikey = old && old == key_mtx_dereference(sdata->local, sdata->default_unicast_key); defmultikey = old && old == key_mtx_dereference(sdata->local, sdata->default_multicast_key); defmgmtkey = old && old == key_mtx_dereference(sdata->local, sdata->default_mgmt_key); |
3b96766f0 mac80211: fix key... |
292 |
|
f7e0104c1 mac80211: support... |
293 294 295 296 |
if (defunikey && !new) __ieee80211_set_default_key(sdata, -1, true, false); if (defmultikey && !new) __ieee80211_set_default_key(sdata, -1, false, true); |
3cfcf6ac6 mac80211: 802.11w... |
297 298 |
if (defmgmtkey && !new) __ieee80211_set_default_mgmt_key(sdata, -1); |
3b96766f0 mac80211: fix key... |
299 300 |
rcu_assign_pointer(sdata->keys[idx], new); |
f7e0104c1 mac80211: support... |
301 302 303 304 305 306 |
if (defunikey && new) __ieee80211_set_default_key(sdata, new->conf.keyidx, true, false); if (defmultikey && new) __ieee80211_set_default_key(sdata, new->conf.keyidx, false, true); |
3cfcf6ac6 mac80211: 802.11w... |
307 308 309 |
if (defmgmtkey && new) __ieee80211_set_default_mgmt_key(sdata, new->conf.keyidx); |
3b96766f0 mac80211: fix key... |
310 |
} |
b5c34f662 mac80211: fix som... |
311 312 |
if (old) list_del(&old->list); |
11a843b7e [MAC80211]: rewor... |
313 |
} |
2475b1cc0 mac80211: add gen... |
314 315 316 317 318 |
struct ieee80211_key * ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, const u8 *key_data, size_t seq_len, const u8 *seq, const struct ieee80211_cipher_scheme *cs) |
1f5a7e47a [MAC80211]: split... |
319 320 |
{ struct ieee80211_key *key; |
1ac62ba7c mac80211: Don't s... |
321 |
int i, j, err; |
1f5a7e47a [MAC80211]: split... |
322 |
|
8c5bb1fad mac80211: remove ... |
323 324 |
if (WARN_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)) return ERR_PTR(-EINVAL); |
11a843b7e [MAC80211]: rewor... |
325 326 |
key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL); |
1f5a7e47a [MAC80211]: split... |
327 |
if (!key) |
1ac62ba7c mac80211: Don't s... |
328 |
return ERR_PTR(-ENOMEM); |
11a843b7e [MAC80211]: rewor... |
329 330 331 332 333 |
/* * Default to software encryption; we'll later upload the * key to the hardware if possible. */ |
11a843b7e [MAC80211]: rewor... |
334 335 |
key->conf.flags = 0; key->flags = 0; |
97359d123 mac80211: use cip... |
336 |
key->conf.cipher = cipher; |
11a843b7e [MAC80211]: rewor... |
337 338 |
key->conf.keyidx = idx; key->conf.keylen = key_len; |
97359d123 mac80211: use cip... |
339 340 341 |
switch (cipher) { case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: |
4325f6caa wireless: move cr... |
342 343 |
key->conf.iv_len = IEEE80211_WEP_IV_LEN; key->conf.icv_len = IEEE80211_WEP_ICV_LEN; |
76708dee3 mac80211: free up... |
344 |
break; |
97359d123 mac80211: use cip... |
345 |
case WLAN_CIPHER_SUITE_TKIP: |
4325f6caa wireless: move cr... |
346 347 |
key->conf.iv_len = IEEE80211_TKIP_IV_LEN; key->conf.icv_len = IEEE80211_TKIP_ICV_LEN; |
9f26a9522 nl80211: Validate... |
348 |
if (seq) { |
5a306f588 mac80211: introdu... |
349 |
for (i = 0; i < IEEE80211_NUM_TIDS; i++) { |
faa8fdc85 nl80211: Add RSC ... |
350 351 352 353 354 355 |
key->u.tkip.rx[i].iv32 = get_unaligned_le32(&seq[2]); key->u.tkip.rx[i].iv16 = get_unaligned_le16(seq); } } |
523b02ea2 mac80211: fix TKI... |
356 |
spin_lock_init(&key->u.tkip.txlock); |
76708dee3 mac80211: free up... |
357 |
break; |
97359d123 mac80211: use cip... |
358 |
case WLAN_CIPHER_SUITE_CCMP: |
4325f6caa wireless: move cr... |
359 360 |
key->conf.iv_len = IEEE80211_CCMP_HDR_LEN; key->conf.icv_len = IEEE80211_CCMP_MIC_LEN; |
9f26a9522 nl80211: Validate... |
361 |
if (seq) { |
5a306f588 mac80211: introdu... |
362 |
for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) |
4325f6caa wireless: move cr... |
363 |
for (j = 0; j < IEEE80211_CCMP_PN_LEN; j++) |
faa8fdc85 nl80211: Add RSC ... |
364 |
key->u.ccmp.rx_pn[i][j] = |
4325f6caa wireless: move cr... |
365 |
seq[IEEE80211_CCMP_PN_LEN - j - 1]; |
faa8fdc85 nl80211: Add RSC ... |
366 |
} |
11a843b7e [MAC80211]: rewor... |
367 368 369 370 |
/* * Initialize AES key state here as an optimization so that * it does not need to be initialized for every packet. */ |
2b2ba0db1 mac80111: Add CCM... |
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 |
key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt( key_data, key_len, IEEE80211_CCMP_MIC_LEN); if (IS_ERR(key->u.ccmp.tfm)) { err = PTR_ERR(key->u.ccmp.tfm); kfree(key); return ERR_PTR(err); } break; case WLAN_CIPHER_SUITE_CCMP_256: key->conf.iv_len = IEEE80211_CCMP_256_HDR_LEN; key->conf.icv_len = IEEE80211_CCMP_256_MIC_LEN; for (i = 0; seq && i < IEEE80211_NUM_TIDS + 1; i++) for (j = 0; j < IEEE80211_CCMP_256_PN_LEN; j++) key->u.ccmp.rx_pn[i][j] = seq[IEEE80211_CCMP_256_PN_LEN - j - 1]; /* Initialize AES key state here as an optimization so that * it does not need to be initialized for every packet. */ key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt( key_data, key_len, IEEE80211_CCMP_256_MIC_LEN); |
1ac62ba7c mac80211: Don't s... |
391 392 |
if (IS_ERR(key->u.ccmp.tfm)) { err = PTR_ERR(key->u.ccmp.tfm); |
3b96766f0 mac80211: fix key... |
393 |
kfree(key); |
1f951a7f8 mac80211: fix NUL... |
394 |
return ERR_PTR(err); |
11a843b7e [MAC80211]: rewor... |
395 |
} |
60ae0f200 mac80211: move ke... |
396 397 |
break; case WLAN_CIPHER_SUITE_AES_CMAC: |
56c52da2d mac80111: Add BIP... |
398 |
case WLAN_CIPHER_SUITE_BIP_CMAC_256: |
60ae0f200 mac80211: move ke... |
399 |
key->conf.iv_len = 0; |
56c52da2d mac80111: Add BIP... |
400 401 402 403 |
if (cipher == WLAN_CIPHER_SUITE_AES_CMAC) key->conf.icv_len = sizeof(struct ieee80211_mmie); else key->conf.icv_len = sizeof(struct ieee80211_mmie_16); |
60ae0f200 mac80211: move ke... |
404 |
if (seq) |
4325f6caa wireless: move cr... |
405 |
for (j = 0; j < IEEE80211_CMAC_PN_LEN; j++) |
0f9273234 mac80211: use CMA... |
406 |
key->u.aes_cmac.rx_pn[j] = |
4325f6caa wireless: move cr... |
407 |
seq[IEEE80211_CMAC_PN_LEN - j - 1]; |
3cfcf6ac6 mac80211: 802.11w... |
408 409 410 411 412 |
/* * Initialize AES key state here as an optimization so that * it does not need to be initialized for every packet. */ key->u.aes_cmac.tfm = |
56c52da2d mac80111: Add BIP... |
413 |
ieee80211_aes_cmac_key_setup(key_data, key_len); |
1ac62ba7c mac80211: Don't s... |
414 415 |
if (IS_ERR(key->u.aes_cmac.tfm)) { err = PTR_ERR(key->u.aes_cmac.tfm); |
3cfcf6ac6 mac80211: 802.11w... |
416 |
kfree(key); |
1f951a7f8 mac80211: fix NUL... |
417 |
return ERR_PTR(err); |
3cfcf6ac6 mac80211: 802.11w... |
418 |
} |
60ae0f200 mac80211: move ke... |
419 |
break; |
8ade538bf mac80111: Add BIP... |
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 |
case WLAN_CIPHER_SUITE_BIP_GMAC_128: case WLAN_CIPHER_SUITE_BIP_GMAC_256: key->conf.iv_len = 0; key->conf.icv_len = sizeof(struct ieee80211_mmie_16); if (seq) for (j = 0; j < IEEE80211_GMAC_PN_LEN; j++) key->u.aes_gmac.rx_pn[j] = seq[IEEE80211_GMAC_PN_LEN - j - 1]; /* Initialize AES key state here as an optimization so that * it does not need to be initialized for every packet. */ key->u.aes_gmac.tfm = ieee80211_aes_gmac_key_setup(key_data, key_len); if (IS_ERR(key->u.aes_gmac.tfm)) { err = PTR_ERR(key->u.aes_gmac.tfm); kfree(key); return ERR_PTR(err); } break; |
00b9cfa3f mac80111: Add GCM... |
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 |
case WLAN_CIPHER_SUITE_GCMP: case WLAN_CIPHER_SUITE_GCMP_256: key->conf.iv_len = IEEE80211_GCMP_HDR_LEN; key->conf.icv_len = IEEE80211_GCMP_MIC_LEN; for (i = 0; seq && i < IEEE80211_NUM_TIDS + 1; i++) for (j = 0; j < IEEE80211_GCMP_PN_LEN; j++) key->u.gcmp.rx_pn[i][j] = seq[IEEE80211_GCMP_PN_LEN - j - 1]; /* Initialize AES key state here as an optimization so that * it does not need to be initialized for every packet. */ key->u.gcmp.tfm = ieee80211_aes_gcm_key_setup_encrypt(key_data, key_len); if (IS_ERR(key->u.gcmp.tfm)) { err = PTR_ERR(key->u.gcmp.tfm); kfree(key); return ERR_PTR(err); } break; |
2475b1cc0 mac80211: add gen... |
458 459 460 461 462 463 464 465 466 467 468 |
default: if (cs) { size_t len = (seq_len > MAX_PN_LEN) ? MAX_PN_LEN : seq_len; key->conf.iv_len = cs->hdr_len; key->conf.icv_len = cs->mic_len; for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) for (j = 0; j < len; j++) key->u.gen.rx_pn[i][j] = seq[len - j - 1]; |
c7ef38e0c mac80211: Get IV ... |
469 |
key->flags |= KEY_FLAG_CIPHER_SCHEME; |
2475b1cc0 mac80211: add gen... |
470 |
} |
3cfcf6ac6 mac80211: 802.11w... |
471 |
} |
60ae0f200 mac80211: move ke... |
472 473 |
memcpy(key->conf.key, key_data, key_len); INIT_LIST_HEAD(&key->list); |
3cfcf6ac6 mac80211: 802.11w... |
474 |
|
db4d1169d mac80211: split i... |
475 476 |
return key; } |
11a843b7e [MAC80211]: rewor... |
477 |
|
79cf2dfa3 mac80211: clean u... |
478 479 |
static void ieee80211_key_free_common(struct ieee80211_key *key) { |
00b9cfa3f mac80111: Add GCM... |
480 481 |
switch (key->conf.cipher) { case WLAN_CIPHER_SUITE_CCMP: |
2b2ba0db1 mac80111: Add CCM... |
482 |
case WLAN_CIPHER_SUITE_CCMP_256: |
79cf2dfa3 mac80211: clean u... |
483 |
ieee80211_aes_key_free(key->u.ccmp.tfm); |
00b9cfa3f mac80111: Add GCM... |
484 485 |
break; case WLAN_CIPHER_SUITE_AES_CMAC: |
56c52da2d mac80111: Add BIP... |
486 |
case WLAN_CIPHER_SUITE_BIP_CMAC_256: |
79cf2dfa3 mac80211: clean u... |
487 |
ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); |
00b9cfa3f mac80111: Add GCM... |
488 |
break; |
8ade538bf mac80111: Add BIP... |
489 490 491 492 |
case WLAN_CIPHER_SUITE_BIP_GMAC_128: case WLAN_CIPHER_SUITE_BIP_GMAC_256: ieee80211_aes_gmac_key_free(key->u.aes_gmac.tfm); break; |
00b9cfa3f mac80111: Add GCM... |
493 494 495 496 497 |
case WLAN_CIPHER_SUITE_GCMP: case WLAN_CIPHER_SUITE_GCMP_256: ieee80211_aes_gcm_key_free(key->u.gcmp.tfm); break; } |
29c3f9c39 mac80211: clear k... |
498 |
kzfree(key); |
79cf2dfa3 mac80211: clean u... |
499 |
} |
6d10e46be mac80211: batch k... |
500 501 |
static void __ieee80211_key_destroy(struct ieee80211_key *key, bool delay_tailroom) |
ad0e2b5a0 mac80211: simplif... |
502 |
{ |
32162a4da mac80211: Fix key... |
503 504 |
if (key->local) ieee80211_key_disable_hw_accel(key); |
ad0e2b5a0 mac80211: simplif... |
505 |
|
3bff18651 mac80211: Skip ta... |
506 |
if (key->local) { |
8d1f7ecd2 mac80211: defer t... |
507 |
struct ieee80211_sub_if_data *sdata = key->sdata; |
32162a4da mac80211: Fix key... |
508 |
ieee80211_debugfs_key_remove(key); |
8d1f7ecd2 mac80211: defer t... |
509 510 511 512 513 514 515 516 517 |
if (delay_tailroom) { /* see ieee80211_delayed_tailroom_dec */ sdata->crypto_tx_tailroom_pending_dec++; schedule_delayed_work(&sdata->dec_tailroom_needed_wk, HZ/2); } else { sdata->crypto_tx_tailroom_needed_cnt--; } |
3bff18651 mac80211: Skip ta... |
518 |
} |
ad0e2b5a0 mac80211: simplif... |
519 |
|
79cf2dfa3 mac80211: clean u... |
520 521 |
ieee80211_key_free_common(key); } |
6d10e46be mac80211: batch k... |
522 523 524 525 526 527 528 529 530 531 532 533 534 535 |
static void ieee80211_key_destroy(struct ieee80211_key *key, bool delay_tailroom) { if (!key) return; /* * Synchronize so the TX path can no longer be using * this key before we free/remove it. */ synchronize_net(); __ieee80211_key_destroy(key, delay_tailroom); } |
79cf2dfa3 mac80211: clean u... |
536 537 538 539 |
void ieee80211_key_free_unused(struct ieee80211_key *key) { WARN_ON(key->sdata || key->local); ieee80211_key_free_common(key); |
ad0e2b5a0 mac80211: simplif... |
540 |
} |
3ffc2a905 mac80211: allow v... |
541 542 543 |
int ieee80211_key_link(struct ieee80211_key *key, struct ieee80211_sub_if_data *sdata, struct sta_info *sta) |
db4d1169d mac80211: split i... |
544 |
{ |
27b3eb9c0 mac80211: add API... |
545 |
struct ieee80211_local *local = sdata->local; |
db4d1169d mac80211: split i... |
546 |
struct ieee80211_key *old_key; |
3ffc2a905 mac80211: allow v... |
547 |
int idx, ret; |
67aa030c0 mac80211: fix pos... |
548 |
bool pairwise; |
db4d1169d mac80211: split i... |
549 |
|
67aa030c0 mac80211: fix pos... |
550 |
pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE; |
db4d1169d mac80211: split i... |
551 552 553 554 |
idx = key->conf.keyidx; key->local = sdata->local; key->sdata = sdata; key->sta = sta; |
ad0e2b5a0 mac80211: simplif... |
555 |
mutex_lock(&sdata->local->key_mtx); |
3b96766f0 mac80211: fix key... |
556 |
|
e31b82136 cfg80211/mac80211... |
557 |
if (sta && pairwise) |
2475b1cc0 mac80211: add gen... |
558 |
old_key = key_mtx_dereference(sdata->local, sta->ptk[idx]); |
e31b82136 cfg80211/mac80211... |
559 |
else if (sta) |
40b275b69 mac80211: sparse ... |
560 |
old_key = key_mtx_dereference(sdata->local, sta->gtk[idx]); |
d4e46a3d9 [MAC80211]: fix r... |
561 |
else |
40b275b69 mac80211: sparse ... |
562 |
old_key = key_mtx_dereference(sdata->local, sdata->keys[idx]); |
db4d1169d mac80211: split i... |
563 |
|
3bff18651 mac80211: Skip ta... |
564 |
increment_tailroom_need_count(sdata); |
3b8d9c290 mac80211: remove ... |
565 566 |
ieee80211_key_replace(sdata, sta, pairwise, old_key, key); ieee80211_key_destroy(old_key, true); |
d4e46a3d9 [MAC80211]: fix r... |
567 |
|
ad0e2b5a0 mac80211: simplif... |
568 |
ieee80211_debugfs_key_add(key); |
db4d1169d mac80211: split i... |
569 |
|
27b3eb9c0 mac80211: add API... |
570 571 572 573 574 575 576 |
if (!local->wowlan) { ret = ieee80211_key_enable_hw_accel(key); if (ret) ieee80211_key_free(key, true); } else { ret = 0; } |
79cf2dfa3 mac80211: clean u... |
577 |
|
ad0e2b5a0 mac80211: simplif... |
578 |
mutex_unlock(&sdata->local->key_mtx); |
3ffc2a905 mac80211: allow v... |
579 580 |
return ret; |
1f5a7e47a [MAC80211]: split... |
581 |
} |
3b8d9c290 mac80211: remove ... |
582 |
void ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom) |
1f5a7e47a [MAC80211]: split... |
583 |
{ |
5c0c36412 mac80211: make ke... |
584 585 |
if (!key) return; |
3b96766f0 mac80211: fix key... |
586 587 588 |
/* * Replace key with nothingness if it was ever used. */ |
3a2457669 mac80211: fix key... |
589 |
if (key->sdata) |
3b8d9c290 mac80211: remove ... |
590 |
ieee80211_key_replace(key->sdata, key->sta, |
e31b82136 cfg80211/mac80211... |
591 592 |
key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, key, NULL); |
3b8d9c290 mac80211: remove ... |
593 |
ieee80211_key_destroy(key, delay_tailroom); |
3b96766f0 mac80211: fix key... |
594 |
} |
d4e46a3d9 [MAC80211]: fix r... |
595 |
|
ad0e2b5a0 mac80211: simplif... |
596 |
void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) |
3a2457669 mac80211: fix key... |
597 598 |
{ struct ieee80211_key *key; |
11a843b7e [MAC80211]: rewor... |
599 |
|
3a2457669 mac80211: fix key... |
600 |
ASSERT_RTNL(); |
11a843b7e [MAC80211]: rewor... |
601 |
|
9607e6b66 mac80211: add iee... |
602 |
if (WARN_ON(!ieee80211_sdata_running(sdata))) |
3a2457669 mac80211: fix key... |
603 |
return; |
11a843b7e [MAC80211]: rewor... |
604 |
|
ad0e2b5a0 mac80211: simplif... |
605 |
mutex_lock(&sdata->local->key_mtx); |
11a843b7e [MAC80211]: rewor... |
606 |
|
3bff18651 mac80211: Skip ta... |
607 608 609 610 |
sdata->crypto_tx_tailroom_needed_cnt = 0; list_for_each_entry(key, &sdata->key_list, list) { increment_tailroom_need_count(sdata); |
ad0e2b5a0 mac80211: simplif... |
611 |
ieee80211_key_enable_hw_accel(key); |
3bff18651 mac80211: Skip ta... |
612 |
} |
3b96766f0 mac80211: fix key... |
613 |
|
ad0e2b5a0 mac80211: simplif... |
614 |
mutex_unlock(&sdata->local->key_mtx); |
11a843b7e [MAC80211]: rewor... |
615 |
} |
830af02f2 mac80211: allow d... |
616 617 618 619 620 621 622 623 624 625 |
void ieee80211_iter_keys(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void (*iter)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key, void *data), void *iter_data) { struct ieee80211_local *local = hw_to_local(hw); |
27b3eb9c0 mac80211: add API... |
626 |
struct ieee80211_key *key, *tmp; |
830af02f2 mac80211: allow d... |
627 628 629 630 631 632 633 |
struct ieee80211_sub_if_data *sdata; ASSERT_RTNL(); mutex_lock(&local->key_mtx); if (vif) { sdata = vif_to_sdata(vif); |
27b3eb9c0 mac80211: add API... |
634 |
list_for_each_entry_safe(key, tmp, &sdata->key_list, list) |
830af02f2 mac80211: allow d... |
635 636 637 638 639 |
iter(hw, &sdata->vif, key->sta ? &key->sta->sta : NULL, &key->conf, iter_data); } else { list_for_each_entry(sdata, &local->interfaces, list) |
27b3eb9c0 mac80211: add API... |
640 641 |
list_for_each_entry_safe(key, tmp, &sdata->key_list, list) |
830af02f2 mac80211: allow d... |
642 643 644 645 646 647 648 |
iter(hw, &sdata->vif, key->sta ? &key->sta->sta : NULL, &key->conf, iter_data); } mutex_unlock(&local->key_mtx); } EXPORT_SYMBOL(ieee80211_iter_keys); |
7907c7d33 mac80211: free al... |
649 650 |
static void ieee80211_free_keys_iface(struct ieee80211_sub_if_data *sdata, struct list_head *keys) |
3b96766f0 mac80211: fix key... |
651 652 |
{ struct ieee80211_key *key, *tmp; |
3b96766f0 mac80211: fix key... |
653 |
|
8d1f7ecd2 mac80211: defer t... |
654 655 656 |
sdata->crypto_tx_tailroom_needed_cnt -= sdata->crypto_tx_tailroom_pending_dec; sdata->crypto_tx_tailroom_pending_dec = 0; |
3cfcf6ac6 mac80211: 802.11w... |
657 |
ieee80211_debugfs_key_remove_mgmt_default(sdata); |
3b96766f0 mac80211: fix key... |
658 |
|
6d10e46be mac80211: batch k... |
659 660 661 662 |
list_for_each_entry_safe(key, tmp, &sdata->key_list, list) { ieee80211_key_replace(key->sdata, key->sta, key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, key, NULL); |
7907c7d33 mac80211: free al... |
663 |
list_add_tail(&key->list, keys); |
6d10e46be mac80211: batch k... |
664 |
} |
3b96766f0 mac80211: fix key... |
665 |
|
f7e0104c1 mac80211: support... |
666 |
ieee80211_debugfs_key_update_default(sdata); |
7907c7d33 mac80211: free al... |
667 |
} |
f7e0104c1 mac80211: support... |
668 |
|
7907c7d33 mac80211: free al... |
669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 |
void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata, bool force_synchronize) { struct ieee80211_local *local = sdata->local; struct ieee80211_sub_if_data *vlan; struct ieee80211_key *key, *tmp; LIST_HEAD(keys); cancel_delayed_work_sync(&sdata->dec_tailroom_needed_wk); mutex_lock(&local->key_mtx); ieee80211_free_keys_iface(sdata, &keys); if (sdata->vif.type == NL80211_IFTYPE_AP) { list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) ieee80211_free_keys_iface(vlan, &keys); |
6d10e46be mac80211: batch k... |
686 |
} |
7907c7d33 mac80211: free al... |
687 688 689 690 |
if (!list_empty(&keys) || force_synchronize) synchronize_net(); list_for_each_entry_safe(key, tmp, &keys, list) __ieee80211_key_destroy(key, false); |
8d1f7ecd2 mac80211: defer t... |
691 692 |
WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt || sdata->crypto_tx_tailroom_pending_dec); |
7907c7d33 mac80211: free al... |
693 694 695 696 697 |
if (sdata->vif.type == NL80211_IFTYPE_AP) { list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) WARN_ON_ONCE(vlan->crypto_tx_tailroom_needed_cnt || vlan->crypto_tx_tailroom_pending_dec); } |
8d1f7ecd2 mac80211: defer t... |
698 |
|
7907c7d33 mac80211: free al... |
699 |
mutex_unlock(&local->key_mtx); |
11a843b7e [MAC80211]: rewor... |
700 |
} |
c68f4b892 mac80211: support... |
701 |
|
6d10e46be mac80211: batch k... |
702 703 704 |
void ieee80211_free_sta_keys(struct ieee80211_local *local, struct sta_info *sta) { |
c87820784 mac80211: move sy... |
705 |
struct ieee80211_key *key; |
6d10e46be mac80211: batch k... |
706 707 708 |
int i; mutex_lock(&local->key_mtx); |
28a9bc681 mac80211: free ma... |
709 |
for (i = 0; i < ARRAY_SIZE(sta->gtk); i++) { |
6d10e46be mac80211: batch k... |
710 711 712 713 714 715 |
key = key_mtx_dereference(local, sta->gtk[i]); if (!key) continue; ieee80211_key_replace(key->sdata, key->sta, key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, key, NULL); |
c87820784 mac80211: move sy... |
716 |
__ieee80211_key_destroy(key, true); |
6d10e46be mac80211: batch k... |
717 |
} |
2475b1cc0 mac80211: add gen... |
718 719 720 721 |
for (i = 0; i < NUM_DEFAULT_KEYS; i++) { key = key_mtx_dereference(local, sta->ptk[i]); if (!key) continue; |
6d10e46be mac80211: batch k... |
722 723 724 |
ieee80211_key_replace(key->sdata, key->sta, key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, key, NULL); |
6d10e46be mac80211: batch k... |
725 |
__ieee80211_key_destroy(key, true); |
c87820784 mac80211: move sy... |
726 |
} |
6d10e46be mac80211: batch k... |
727 728 729 |
mutex_unlock(&local->key_mtx); } |
8d1f7ecd2 mac80211: defer t... |
730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 |
void ieee80211_delayed_tailroom_dec(struct work_struct *wk) { struct ieee80211_sub_if_data *sdata; sdata = container_of(wk, struct ieee80211_sub_if_data, dec_tailroom_needed_wk.work); /* * The reason for the delayed tailroom needed decrementing is to * make roaming faster: during roaming, all keys are first deleted * and then new keys are installed. The first new key causes the * crypto_tx_tailroom_needed_cnt to go from 0 to 1, which invokes * the cost of synchronize_net() (which can be slow). Avoid this * by deferring the crypto_tx_tailroom_needed_cnt decrementing on * key removal for a while, so if we roam the value is larger than * zero and no 0->1 transition happens. * * The cost is that if the AP switching was from an AP with keys * to one without, we still allocate tailroom while it would no * longer be needed. However, in the typical (fast) roaming case * within an ESS this usually won't happen. */ mutex_lock(&sdata->local->key_mtx); sdata->crypto_tx_tailroom_needed_cnt -= sdata->crypto_tx_tailroom_pending_dec; sdata->crypto_tx_tailroom_pending_dec = 0; mutex_unlock(&sdata->local->key_mtx); } |
c68f4b892 mac80211: support... |
759 760 761 762 763 764 765 766 767 768 769 |
void ieee80211_gtk_rekey_notify(struct ieee80211_vif *vif, const u8 *bssid, const u8 *replay_ctr, gfp_t gfp) { struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); trace_api_gtk_rekey_notify(sdata, bssid, replay_ctr); cfg80211_gtk_rekey_notify(sdata->dev, bssid, replay_ctr, gfp); } EXPORT_SYMBOL_GPL(ieee80211_gtk_rekey_notify); |
3ea542d3c mac80211: allow d... |
770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 |
void ieee80211_get_key_tx_seq(struct ieee80211_key_conf *keyconf, struct ieee80211_key_seq *seq) { struct ieee80211_key *key; u64 pn64; if (WARN_ON(!(keyconf->flags & IEEE80211_KEY_FLAG_GENERATE_IV))) return; key = container_of(keyconf, struct ieee80211_key, conf); switch (key->conf.cipher) { case WLAN_CIPHER_SUITE_TKIP: seq->tkip.iv32 = key->u.tkip.tx.iv32; seq->tkip.iv16 = key->u.tkip.tx.iv16; break; case WLAN_CIPHER_SUITE_CCMP: |
2b2ba0db1 mac80111: Add CCM... |
788 |
case WLAN_CIPHER_SUITE_CCMP_256: |
3ea542d3c mac80211: allow d... |
789 790 791 792 793 794 795 796 797 |
pn64 = atomic64_read(&key->u.ccmp.tx_pn); seq->ccmp.pn[5] = pn64; seq->ccmp.pn[4] = pn64 >> 8; seq->ccmp.pn[3] = pn64 >> 16; seq->ccmp.pn[2] = pn64 >> 24; seq->ccmp.pn[1] = pn64 >> 32; seq->ccmp.pn[0] = pn64 >> 40; break; case WLAN_CIPHER_SUITE_AES_CMAC: |
56c52da2d mac80111: Add BIP... |
798 |
case WLAN_CIPHER_SUITE_BIP_CMAC_256: |
3ea542d3c mac80211: allow d... |
799 800 801 802 803 804 805 806 |
pn64 = atomic64_read(&key->u.aes_cmac.tx_pn); seq->ccmp.pn[5] = pn64; seq->ccmp.pn[4] = pn64 >> 8; seq->ccmp.pn[3] = pn64 >> 16; seq->ccmp.pn[2] = pn64 >> 24; seq->ccmp.pn[1] = pn64 >> 32; seq->ccmp.pn[0] = pn64 >> 40; break; |
8ade538bf mac80111: Add BIP... |
807 808 809 810 811 812 813 814 815 816 |
case WLAN_CIPHER_SUITE_BIP_GMAC_128: case WLAN_CIPHER_SUITE_BIP_GMAC_256: pn64 = atomic64_read(&key->u.aes_gmac.tx_pn); seq->ccmp.pn[5] = pn64; seq->ccmp.pn[4] = pn64 >> 8; seq->ccmp.pn[3] = pn64 >> 16; seq->ccmp.pn[2] = pn64 >> 24; seq->ccmp.pn[1] = pn64 >> 32; seq->ccmp.pn[0] = pn64 >> 40; break; |
00b9cfa3f mac80111: Add GCM... |
817 818 819 820 821 822 823 824 825 826 |
case WLAN_CIPHER_SUITE_GCMP: case WLAN_CIPHER_SUITE_GCMP_256: pn64 = atomic64_read(&key->u.gcmp.tx_pn); seq->gcmp.pn[5] = pn64; seq->gcmp.pn[4] = pn64 >> 8; seq->gcmp.pn[3] = pn64 >> 16; seq->gcmp.pn[2] = pn64 >> 24; seq->gcmp.pn[1] = pn64 >> 32; seq->gcmp.pn[0] = pn64 >> 40; break; |
3ea542d3c mac80211: allow d... |
827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 |
default: WARN_ON(1); } } EXPORT_SYMBOL(ieee80211_get_key_tx_seq); void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf, int tid, struct ieee80211_key_seq *seq) { struct ieee80211_key *key; const u8 *pn; key = container_of(keyconf, struct ieee80211_key, conf); switch (key->conf.cipher) { case WLAN_CIPHER_SUITE_TKIP: |
5a306f588 mac80211: introdu... |
843 |
if (WARN_ON(tid < 0 || tid >= IEEE80211_NUM_TIDS)) |
3ea542d3c mac80211: allow d... |
844 845 846 847 848 |
return; seq->tkip.iv32 = key->u.tkip.rx[tid].iv32; seq->tkip.iv16 = key->u.tkip.rx[tid].iv16; break; case WLAN_CIPHER_SUITE_CCMP: |
2b2ba0db1 mac80111: Add CCM... |
849 |
case WLAN_CIPHER_SUITE_CCMP_256: |
5a306f588 mac80211: introdu... |
850 |
if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS)) |
3ea542d3c mac80211: allow d... |
851 852 |
return; if (tid < 0) |
5a306f588 mac80211: introdu... |
853 |
pn = key->u.ccmp.rx_pn[IEEE80211_NUM_TIDS]; |
3ea542d3c mac80211: allow d... |
854 855 |
else pn = key->u.ccmp.rx_pn[tid]; |
4325f6caa wireless: move cr... |
856 |
memcpy(seq->ccmp.pn, pn, IEEE80211_CCMP_PN_LEN); |
3ea542d3c mac80211: allow d... |
857 858 |
break; case WLAN_CIPHER_SUITE_AES_CMAC: |
56c52da2d mac80111: Add BIP... |
859 |
case WLAN_CIPHER_SUITE_BIP_CMAC_256: |
3ea542d3c mac80211: allow d... |
860 861 862 |
if (WARN_ON(tid != 0)) return; pn = key->u.aes_cmac.rx_pn; |
4325f6caa wireless: move cr... |
863 |
memcpy(seq->aes_cmac.pn, pn, IEEE80211_CMAC_PN_LEN); |
3ea542d3c mac80211: allow d... |
864 |
break; |
8ade538bf mac80111: Add BIP... |
865 866 867 868 869 870 871 |
case WLAN_CIPHER_SUITE_BIP_GMAC_128: case WLAN_CIPHER_SUITE_BIP_GMAC_256: if (WARN_ON(tid != 0)) return; pn = key->u.aes_gmac.rx_pn; memcpy(seq->aes_gmac.pn, pn, IEEE80211_GMAC_PN_LEN); break; |
00b9cfa3f mac80111: Add GCM... |
872 873 874 875 876 877 878 879 880 881 |
case WLAN_CIPHER_SUITE_GCMP: case WLAN_CIPHER_SUITE_GCMP_256: if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS)) return; if (tid < 0) pn = key->u.gcmp.rx_pn[IEEE80211_NUM_TIDS]; else pn = key->u.gcmp.rx_pn[tid]; memcpy(seq->gcmp.pn, pn, IEEE80211_GCMP_PN_LEN); break; |
3ea542d3c mac80211: allow d... |
882 883 884 |
} } EXPORT_SYMBOL(ieee80211_get_key_rx_seq); |
27b3eb9c0 mac80211: add API... |
885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 |
void ieee80211_set_key_tx_seq(struct ieee80211_key_conf *keyconf, struct ieee80211_key_seq *seq) { struct ieee80211_key *key; u64 pn64; key = container_of(keyconf, struct ieee80211_key, conf); switch (key->conf.cipher) { case WLAN_CIPHER_SUITE_TKIP: key->u.tkip.tx.iv32 = seq->tkip.iv32; key->u.tkip.tx.iv16 = seq->tkip.iv16; break; case WLAN_CIPHER_SUITE_CCMP: |
2b2ba0db1 mac80111: Add CCM... |
900 |
case WLAN_CIPHER_SUITE_CCMP_256: |
27b3eb9c0 mac80211: add API... |
901 902 903 904 905 906 907 908 909 |
pn64 = (u64)seq->ccmp.pn[5] | ((u64)seq->ccmp.pn[4] << 8) | ((u64)seq->ccmp.pn[3] << 16) | ((u64)seq->ccmp.pn[2] << 24) | ((u64)seq->ccmp.pn[1] << 32) | ((u64)seq->ccmp.pn[0] << 40); atomic64_set(&key->u.ccmp.tx_pn, pn64); break; case WLAN_CIPHER_SUITE_AES_CMAC: |
56c52da2d mac80111: Add BIP... |
910 |
case WLAN_CIPHER_SUITE_BIP_CMAC_256: |
27b3eb9c0 mac80211: add API... |
911 912 913 914 915 916 917 918 |
pn64 = (u64)seq->aes_cmac.pn[5] | ((u64)seq->aes_cmac.pn[4] << 8) | ((u64)seq->aes_cmac.pn[3] << 16) | ((u64)seq->aes_cmac.pn[2] << 24) | ((u64)seq->aes_cmac.pn[1] << 32) | ((u64)seq->aes_cmac.pn[0] << 40); atomic64_set(&key->u.aes_cmac.tx_pn, pn64); break; |
8ade538bf mac80111: Add BIP... |
919 920 921 922 923 924 925 926 927 928 |
case WLAN_CIPHER_SUITE_BIP_GMAC_128: case WLAN_CIPHER_SUITE_BIP_GMAC_256: pn64 = (u64)seq->aes_gmac.pn[5] | ((u64)seq->aes_gmac.pn[4] << 8) | ((u64)seq->aes_gmac.pn[3] << 16) | ((u64)seq->aes_gmac.pn[2] << 24) | ((u64)seq->aes_gmac.pn[1] << 32) | ((u64)seq->aes_gmac.pn[0] << 40); atomic64_set(&key->u.aes_gmac.tx_pn, pn64); break; |
00b9cfa3f mac80111: Add GCM... |
929 930 931 932 933 934 935 936 937 938 |
case WLAN_CIPHER_SUITE_GCMP: case WLAN_CIPHER_SUITE_GCMP_256: pn64 = (u64)seq->gcmp.pn[5] | ((u64)seq->gcmp.pn[4] << 8) | ((u64)seq->gcmp.pn[3] << 16) | ((u64)seq->gcmp.pn[2] << 24) | ((u64)seq->gcmp.pn[1] << 32) | ((u64)seq->gcmp.pn[0] << 40); atomic64_set(&key->u.gcmp.tx_pn, pn64); break; |
27b3eb9c0 mac80211: add API... |
939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 |
default: WARN_ON(1); break; } } EXPORT_SYMBOL_GPL(ieee80211_set_key_tx_seq); void ieee80211_set_key_rx_seq(struct ieee80211_key_conf *keyconf, int tid, struct ieee80211_key_seq *seq) { struct ieee80211_key *key; u8 *pn; key = container_of(keyconf, struct ieee80211_key, conf); switch (key->conf.cipher) { case WLAN_CIPHER_SUITE_TKIP: if (WARN_ON(tid < 0 || tid >= IEEE80211_NUM_TIDS)) return; key->u.tkip.rx[tid].iv32 = seq->tkip.iv32; key->u.tkip.rx[tid].iv16 = seq->tkip.iv16; break; case WLAN_CIPHER_SUITE_CCMP: |
2b2ba0db1 mac80111: Add CCM... |
962 |
case WLAN_CIPHER_SUITE_CCMP_256: |
27b3eb9c0 mac80211: add API... |
963 964 965 966 967 968 969 970 971 |
if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS)) return; if (tid < 0) pn = key->u.ccmp.rx_pn[IEEE80211_NUM_TIDS]; else pn = key->u.ccmp.rx_pn[tid]; memcpy(pn, seq->ccmp.pn, IEEE80211_CCMP_PN_LEN); break; case WLAN_CIPHER_SUITE_AES_CMAC: |
56c52da2d mac80111: Add BIP... |
972 |
case WLAN_CIPHER_SUITE_BIP_CMAC_256: |
27b3eb9c0 mac80211: add API... |
973 974 975 976 977 |
if (WARN_ON(tid != 0)) return; pn = key->u.aes_cmac.rx_pn; memcpy(pn, seq->aes_cmac.pn, IEEE80211_CMAC_PN_LEN); break; |
8ade538bf mac80111: Add BIP... |
978 979 980 981 982 983 984 |
case WLAN_CIPHER_SUITE_BIP_GMAC_128: case WLAN_CIPHER_SUITE_BIP_GMAC_256: if (WARN_ON(tid != 0)) return; pn = key->u.aes_gmac.rx_pn; memcpy(pn, seq->aes_gmac.pn, IEEE80211_GMAC_PN_LEN); break; |
00b9cfa3f mac80111: Add GCM... |
985 986 987 988 989 990 991 992 993 994 |
case WLAN_CIPHER_SUITE_GCMP: case WLAN_CIPHER_SUITE_GCMP_256: if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS)) return; if (tid < 0) pn = key->u.gcmp.rx_pn[IEEE80211_NUM_TIDS]; else pn = key->u.gcmp.rx_pn[tid]; memcpy(pn, seq->gcmp.pn, IEEE80211_GCMP_PN_LEN); break; |
27b3eb9c0 mac80211: add API... |
995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 |
default: WARN_ON(1); break; } } EXPORT_SYMBOL_GPL(ieee80211_set_key_rx_seq); void ieee80211_remove_key(struct ieee80211_key_conf *keyconf) { struct ieee80211_key *key; key = container_of(keyconf, struct ieee80211_key, conf); assert_key_lock(key->local); /* * if key was uploaded, we assume the driver will/has remove(d) * it, so adjust bookkeeping accordingly */ if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; |
1e359a5de Revert "mac80211:... |
1016 |
if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || |
db12847ca mac80211: Re-fix ... |
1017 |
(key->conf.flags & IEEE80211_KEY_FLAG_RESERVE_TAILROOM))) |
27b3eb9c0 mac80211: add API... |
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 |
increment_tailroom_need_count(key->sdata); } ieee80211_key_free(key, false); } EXPORT_SYMBOL_GPL(ieee80211_remove_key); struct ieee80211_key_conf * ieee80211_gtk_rekey_add(struct ieee80211_vif *vif, struct ieee80211_key_conf *keyconf) { struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); struct ieee80211_local *local = sdata->local; struct ieee80211_key *key; int err; if (WARN_ON(!local->wowlan)) return ERR_PTR(-EINVAL); if (WARN_ON(vif->type != NL80211_IFTYPE_STATION)) return ERR_PTR(-EINVAL); key = ieee80211_key_alloc(keyconf->cipher, keyconf->keyidx, keyconf->keylen, keyconf->key, |
2475b1cc0 mac80211: add gen... |
1042 |
0, NULL, NULL); |
27b3eb9c0 mac80211: add API... |
1043 |
if (IS_ERR(key)) |
c5dc164df mac80211: use ERR... |
1044 |
return ERR_CAST(key); |
27b3eb9c0 mac80211: add API... |
1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 |
if (sdata->u.mgd.mfp != IEEE80211_MFP_DISABLED) key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT; err = ieee80211_key_link(key, sdata, NULL); if (err) return ERR_PTR(err); return &key->conf; } EXPORT_SYMBOL_GPL(ieee80211_gtk_rekey_add); |