1 | #include <machine/rtems-bsd-kernel-space.h> |
---|
2 | |
---|
3 | /*- |
---|
4 | * Copyright (c) 2001 Atsushi Onoe |
---|
5 | * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting |
---|
6 | * All rights reserved. |
---|
7 | * |
---|
8 | * Redistribution and use in source and binary forms, with or without |
---|
9 | * modification, are permitted provided that the following conditions |
---|
10 | * are met: |
---|
11 | * 1. Redistributions of source code must retain the above copyright |
---|
12 | * notice, this list of conditions and the following disclaimer. |
---|
13 | * 2. Redistributions in binary form must reproduce the above copyright |
---|
14 | * notice, this list of conditions and the following disclaimer in the |
---|
15 | * documentation and/or other materials provided with the distribution. |
---|
16 | * |
---|
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
---|
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
---|
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
---|
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
---|
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
---|
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
---|
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
---|
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
---|
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
---|
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
---|
27 | */ |
---|
28 | |
---|
29 | #include <sys/cdefs.h> |
---|
30 | __FBSDID("$FreeBSD$"); |
---|
31 | |
---|
32 | /* |
---|
33 | * IEEE 802.11 generic crypto support. |
---|
34 | */ |
---|
35 | #include <rtems/bsd/local/opt_wlan.h> |
---|
36 | |
---|
37 | #include <rtems/bsd/sys/param.h> |
---|
38 | #include <sys/kernel.h> |
---|
39 | #include <sys/malloc.h> |
---|
40 | #include <sys/mbuf.h> |
---|
41 | |
---|
42 | #include <sys/socket.h> |
---|
43 | |
---|
44 | #include <net/if.h> |
---|
45 | #include <net/if_media.h> |
---|
46 | #include <net/ethernet.h> /* XXX ETHER_HDR_LEN */ |
---|
47 | |
---|
48 | #include <net80211/ieee80211_var.h> |
---|
49 | |
---|
50 | MALLOC_DEFINE(M_80211_CRYPTO, "80211crypto", "802.11 crypto state"); |
---|
51 | |
---|
52 | static int _ieee80211_crypto_delkey(struct ieee80211vap *, |
---|
53 | struct ieee80211_key *); |
---|
54 | |
---|
55 | /* |
---|
56 | * Table of registered cipher modules. |
---|
57 | */ |
---|
58 | static const struct ieee80211_cipher *ciphers[IEEE80211_CIPHER_MAX]; |
---|
59 | |
---|
60 | /* |
---|
61 | * Default "null" key management routines. |
---|
62 | */ |
---|
63 | static int |
---|
64 | null_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k, |
---|
65 | ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix) |
---|
66 | { |
---|
67 | if (!(&vap->iv_nw_keys[0] <= k && |
---|
68 | k < &vap->iv_nw_keys[IEEE80211_WEP_NKID])) { |
---|
69 | /* |
---|
70 | * Not in the global key table, the driver should handle this |
---|
71 | * by allocating a slot in the h/w key table/cache. In |
---|
72 | * lieu of that return key slot 0 for any unicast key |
---|
73 | * request. We disallow the request if this is a group key. |
---|
74 | * This default policy does the right thing for legacy hardware |
---|
75 | * with a 4 key table. It also handles devices that pass |
---|
76 | * packets through untouched when marked with the WEP bit |
---|
77 | * and key index 0. |
---|
78 | */ |
---|
79 | if (k->wk_flags & IEEE80211_KEY_GROUP) |
---|
80 | return 0; |
---|
81 | *keyix = 0; /* NB: use key index 0 for ucast key */ |
---|
82 | } else { |
---|
83 | *keyix = ieee80211_crypto_get_key_wepidx(vap, k); |
---|
84 | } |
---|
85 | *rxkeyix = IEEE80211_KEYIX_NONE; /* XXX maybe *keyix? */ |
---|
86 | return 1; |
---|
87 | } |
---|
88 | static int |
---|
89 | null_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k) |
---|
90 | { |
---|
91 | return 1; |
---|
92 | } |
---|
93 | static int |
---|
94 | null_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k) |
---|
95 | { |
---|
96 | return 1; |
---|
97 | } |
---|
98 | static void null_key_update(struct ieee80211vap *vap) {} |
---|
99 | |
---|
100 | /* |
---|
101 | * Write-arounds for common operations. |
---|
102 | */ |
---|
103 | static __inline void |
---|
104 | cipher_detach(struct ieee80211_key *key) |
---|
105 | { |
---|
106 | key->wk_cipher->ic_detach(key); |
---|
107 | } |
---|
108 | |
---|
109 | static __inline void * |
---|
110 | cipher_attach(struct ieee80211vap *vap, struct ieee80211_key *key) |
---|
111 | { |
---|
112 | return key->wk_cipher->ic_attach(vap, key); |
---|
113 | } |
---|
114 | |
---|
115 | /* |
---|
116 | * Wrappers for driver key management methods. |
---|
117 | */ |
---|
118 | static __inline int |
---|
119 | dev_key_alloc(struct ieee80211vap *vap, |
---|
120 | struct ieee80211_key *key, |
---|
121 | ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix) |
---|
122 | { |
---|
123 | return vap->iv_key_alloc(vap, key, keyix, rxkeyix); |
---|
124 | } |
---|
125 | |
---|
126 | static __inline int |
---|
127 | dev_key_delete(struct ieee80211vap *vap, |
---|
128 | const struct ieee80211_key *key) |
---|
129 | { |
---|
130 | return vap->iv_key_delete(vap, key); |
---|
131 | } |
---|
132 | |
---|
133 | static __inline int |
---|
134 | dev_key_set(struct ieee80211vap *vap, const struct ieee80211_key *key) |
---|
135 | { |
---|
136 | return vap->iv_key_set(vap, key); |
---|
137 | } |
---|
138 | |
---|
139 | /* |
---|
140 | * Setup crypto support for a device/shared instance. |
---|
141 | */ |
---|
142 | void |
---|
143 | ieee80211_crypto_attach(struct ieee80211com *ic) |
---|
144 | { |
---|
145 | /* NB: we assume everything is pre-zero'd */ |
---|
146 | ciphers[IEEE80211_CIPHER_NONE] = &ieee80211_cipher_none; |
---|
147 | } |
---|
148 | |
---|
149 | /* |
---|
150 | * Teardown crypto support. |
---|
151 | */ |
---|
152 | void |
---|
153 | ieee80211_crypto_detach(struct ieee80211com *ic) |
---|
154 | { |
---|
155 | } |
---|
156 | |
---|
157 | /* |
---|
158 | * Setup crypto support for a vap. |
---|
159 | */ |
---|
160 | void |
---|
161 | ieee80211_crypto_vattach(struct ieee80211vap *vap) |
---|
162 | { |
---|
163 | int i; |
---|
164 | |
---|
165 | /* NB: we assume everything is pre-zero'd */ |
---|
166 | vap->iv_max_keyix = IEEE80211_WEP_NKID; |
---|
167 | vap->iv_def_txkey = IEEE80211_KEYIX_NONE; |
---|
168 | for (i = 0; i < IEEE80211_WEP_NKID; i++) |
---|
169 | ieee80211_crypto_resetkey(vap, &vap->iv_nw_keys[i], |
---|
170 | IEEE80211_KEYIX_NONE); |
---|
171 | /* |
---|
172 | * Initialize the driver key support routines to noop entries. |
---|
173 | * This is useful especially for the cipher test modules. |
---|
174 | */ |
---|
175 | vap->iv_key_alloc = null_key_alloc; |
---|
176 | vap->iv_key_set = null_key_set; |
---|
177 | vap->iv_key_delete = null_key_delete; |
---|
178 | vap->iv_key_update_begin = null_key_update; |
---|
179 | vap->iv_key_update_end = null_key_update; |
---|
180 | } |
---|
181 | |
---|
182 | /* |
---|
183 | * Teardown crypto support for a vap. |
---|
184 | */ |
---|
185 | void |
---|
186 | ieee80211_crypto_vdetach(struct ieee80211vap *vap) |
---|
187 | { |
---|
188 | ieee80211_crypto_delglobalkeys(vap); |
---|
189 | } |
---|
190 | |
---|
191 | /* |
---|
192 | * Register a crypto cipher module. |
---|
193 | */ |
---|
194 | void |
---|
195 | ieee80211_crypto_register(const struct ieee80211_cipher *cip) |
---|
196 | { |
---|
197 | if (cip->ic_cipher >= IEEE80211_CIPHER_MAX) { |
---|
198 | printf("%s: cipher %s has an invalid cipher index %u\n", |
---|
199 | __func__, cip->ic_name, cip->ic_cipher); |
---|
200 | return; |
---|
201 | } |
---|
202 | if (ciphers[cip->ic_cipher] != NULL && ciphers[cip->ic_cipher] != cip) { |
---|
203 | printf("%s: cipher %s registered with a different template\n", |
---|
204 | __func__, cip->ic_name); |
---|
205 | return; |
---|
206 | } |
---|
207 | ciphers[cip->ic_cipher] = cip; |
---|
208 | } |
---|
209 | |
---|
210 | /* |
---|
211 | * Unregister a crypto cipher module. |
---|
212 | */ |
---|
213 | void |
---|
214 | ieee80211_crypto_unregister(const struct ieee80211_cipher *cip) |
---|
215 | { |
---|
216 | if (cip->ic_cipher >= IEEE80211_CIPHER_MAX) { |
---|
217 | printf("%s: cipher %s has an invalid cipher index %u\n", |
---|
218 | __func__, cip->ic_name, cip->ic_cipher); |
---|
219 | return; |
---|
220 | } |
---|
221 | if (ciphers[cip->ic_cipher] != NULL && ciphers[cip->ic_cipher] != cip) { |
---|
222 | printf("%s: cipher %s registered with a different template\n", |
---|
223 | __func__, cip->ic_name); |
---|
224 | return; |
---|
225 | } |
---|
226 | /* NB: don't complain about not being registered */ |
---|
227 | /* XXX disallow if references */ |
---|
228 | ciphers[cip->ic_cipher] = NULL; |
---|
229 | } |
---|
230 | |
---|
231 | int |
---|
232 | ieee80211_crypto_available(u_int cipher) |
---|
233 | { |
---|
234 | return cipher < IEEE80211_CIPHER_MAX && ciphers[cipher] != NULL; |
---|
235 | } |
---|
236 | |
---|
237 | /* XXX well-known names! */ |
---|
238 | static const char *cipher_modnames[IEEE80211_CIPHER_MAX] = { |
---|
239 | [IEEE80211_CIPHER_WEP] = "wlan_wep", |
---|
240 | [IEEE80211_CIPHER_TKIP] = "wlan_tkip", |
---|
241 | [IEEE80211_CIPHER_AES_OCB] = "wlan_aes_ocb", |
---|
242 | [IEEE80211_CIPHER_AES_CCM] = "wlan_ccmp", |
---|
243 | [IEEE80211_CIPHER_TKIPMIC] = "#4", /* NB: reserved */ |
---|
244 | [IEEE80211_CIPHER_CKIP] = "wlan_ckip", |
---|
245 | [IEEE80211_CIPHER_NONE] = "wlan_none", |
---|
246 | }; |
---|
247 | |
---|
248 | /* NB: there must be no overlap between user-supplied and device-owned flags */ |
---|
249 | CTASSERT((IEEE80211_KEY_COMMON & IEEE80211_KEY_DEVICE) == 0); |
---|
250 | |
---|
251 | /* |
---|
252 | * Establish a relationship between the specified key and cipher |
---|
253 | * and, if necessary, allocate a hardware index from the driver. |
---|
254 | * Note that when a fixed key index is required it must be specified. |
---|
255 | * |
---|
256 | * This must be the first call applied to a key; all the other key |
---|
257 | * routines assume wk_cipher is setup. |
---|
258 | * |
---|
259 | * Locking must be handled by the caller using: |
---|
260 | * ieee80211_key_update_begin(vap); |
---|
261 | * ieee80211_key_update_end(vap); |
---|
262 | */ |
---|
263 | int |
---|
264 | ieee80211_crypto_newkey(struct ieee80211vap *vap, |
---|
265 | int cipher, int flags, struct ieee80211_key *key) |
---|
266 | { |
---|
267 | struct ieee80211com *ic = vap->iv_ic; |
---|
268 | const struct ieee80211_cipher *cip; |
---|
269 | ieee80211_keyix keyix, rxkeyix; |
---|
270 | void *keyctx; |
---|
271 | int oflags; |
---|
272 | |
---|
273 | IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, |
---|
274 | "%s: cipher %u flags 0x%x keyix %u\n", |
---|
275 | __func__, cipher, flags, key->wk_keyix); |
---|
276 | |
---|
277 | /* |
---|
278 | * Validate cipher and set reference to cipher routines. |
---|
279 | */ |
---|
280 | if (cipher >= IEEE80211_CIPHER_MAX) { |
---|
281 | IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, |
---|
282 | "%s: invalid cipher %u\n", __func__, cipher); |
---|
283 | vap->iv_stats.is_crypto_badcipher++; |
---|
284 | return 0; |
---|
285 | } |
---|
286 | cip = ciphers[cipher]; |
---|
287 | if (cip == NULL) { |
---|
288 | /* |
---|
289 | * Auto-load cipher module if we have a well-known name |
---|
290 | * for it. It might be better to use string names rather |
---|
291 | * than numbers and craft a module name based on the cipher |
---|
292 | * name; e.g. wlan_cipher_<cipher-name>. |
---|
293 | */ |
---|
294 | IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, |
---|
295 | "%s: unregistered cipher %u, load module %s\n", |
---|
296 | __func__, cipher, cipher_modnames[cipher]); |
---|
297 | ieee80211_load_module(cipher_modnames[cipher]); |
---|
298 | /* |
---|
299 | * If cipher module loaded it should immediately |
---|
300 | * call ieee80211_crypto_register which will fill |
---|
301 | * in the entry in the ciphers array. |
---|
302 | */ |
---|
303 | cip = ciphers[cipher]; |
---|
304 | if (cip == NULL) { |
---|
305 | IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, |
---|
306 | "%s: unable to load cipher %u, module %s\n", |
---|
307 | __func__, cipher, cipher_modnames[cipher]); |
---|
308 | vap->iv_stats.is_crypto_nocipher++; |
---|
309 | return 0; |
---|
310 | } |
---|
311 | } |
---|
312 | |
---|
313 | oflags = key->wk_flags; |
---|
314 | flags &= IEEE80211_KEY_COMMON; |
---|
315 | /* NB: preserve device attributes */ |
---|
316 | flags |= (oflags & IEEE80211_KEY_DEVICE); |
---|
317 | /* |
---|
318 | * If the hardware does not support the cipher then |
---|
319 | * fallback to a host-based implementation. |
---|
320 | */ |
---|
321 | if ((ic->ic_cryptocaps & (1<<cipher)) == 0) { |
---|
322 | IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, |
---|
323 | "%s: no h/w support for cipher %s, falling back to s/w\n", |
---|
324 | __func__, cip->ic_name); |
---|
325 | flags |= IEEE80211_KEY_SWCRYPT; |
---|
326 | } |
---|
327 | /* |
---|
328 | * Hardware TKIP with software MIC is an important |
---|
329 | * combination; we handle it by flagging each key, |
---|
330 | * the cipher modules honor it. |
---|
331 | */ |
---|
332 | if (cipher == IEEE80211_CIPHER_TKIP && |
---|
333 | (ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIPMIC) == 0) { |
---|
334 | IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, |
---|
335 | "%s: no h/w support for TKIP MIC, falling back to s/w\n", |
---|
336 | __func__); |
---|
337 | flags |= IEEE80211_KEY_SWMIC; |
---|
338 | } |
---|
339 | |
---|
340 | /* |
---|
341 | * Bind cipher to key instance. Note we do this |
---|
342 | * after checking the device capabilities so the |
---|
343 | * cipher module can optimize space usage based on |
---|
344 | * whether or not it needs to do the cipher work. |
---|
345 | */ |
---|
346 | if (key->wk_cipher != cip || key->wk_flags != flags) { |
---|
347 | /* |
---|
348 | * Fillin the flags so cipher modules can see s/w |
---|
349 | * crypto requirements and potentially allocate |
---|
350 | * different state and/or attach different method |
---|
351 | * pointers. |
---|
352 | */ |
---|
353 | key->wk_flags = flags; |
---|
354 | keyctx = cip->ic_attach(vap, key); |
---|
355 | if (keyctx == NULL) { |
---|
356 | IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, |
---|
357 | "%s: unable to attach cipher %s\n", |
---|
358 | __func__, cip->ic_name); |
---|
359 | key->wk_flags = oflags; /* restore old flags */ |
---|
360 | vap->iv_stats.is_crypto_attachfail++; |
---|
361 | return 0; |
---|
362 | } |
---|
363 | cipher_detach(key); |
---|
364 | key->wk_cipher = cip; /* XXX refcnt? */ |
---|
365 | key->wk_private = keyctx; |
---|
366 | } |
---|
367 | |
---|
368 | /* |
---|
369 | * Ask the driver for a key index if we don't have one. |
---|
370 | * Note that entries in the global key table always have |
---|
371 | * an index; this means it's safe to call this routine |
---|
372 | * for these entries just to setup the reference to the |
---|
373 | * cipher template. Note also that when using software |
---|
374 | * crypto we also call the driver to give us a key index. |
---|
375 | */ |
---|
376 | if ((key->wk_flags & IEEE80211_KEY_DEVKEY) == 0) { |
---|
377 | if (!dev_key_alloc(vap, key, &keyix, &rxkeyix)) { |
---|
378 | /* |
---|
379 | * Unable to setup driver state. |
---|
380 | */ |
---|
381 | vap->iv_stats.is_crypto_keyfail++; |
---|
382 | IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, |
---|
383 | "%s: unable to setup cipher %s\n", |
---|
384 | __func__, cip->ic_name); |
---|
385 | return 0; |
---|
386 | } |
---|
387 | if (key->wk_flags != flags) { |
---|
388 | /* |
---|
389 | * Driver overrode flags we setup; typically because |
---|
390 | * resources were unavailable to handle _this_ key. |
---|
391 | * Re-attach the cipher context to allow cipher |
---|
392 | * modules to handle differing requirements. |
---|
393 | */ |
---|
394 | IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, |
---|
395 | "%s: driver override for cipher %s, flags " |
---|
396 | "0x%x -> 0x%x\n", __func__, cip->ic_name, |
---|
397 | oflags, key->wk_flags); |
---|
398 | keyctx = cip->ic_attach(vap, key); |
---|
399 | if (keyctx == NULL) { |
---|
400 | IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, |
---|
401 | "%s: unable to attach cipher %s with " |
---|
402 | "flags 0x%x\n", __func__, cip->ic_name, |
---|
403 | key->wk_flags); |
---|
404 | key->wk_flags = oflags; /* restore old flags */ |
---|
405 | vap->iv_stats.is_crypto_attachfail++; |
---|
406 | return 0; |
---|
407 | } |
---|
408 | cipher_detach(key); |
---|
409 | key->wk_cipher = cip; /* XXX refcnt? */ |
---|
410 | key->wk_private = keyctx; |
---|
411 | } |
---|
412 | key->wk_keyix = keyix; |
---|
413 | key->wk_rxkeyix = rxkeyix; |
---|
414 | key->wk_flags |= IEEE80211_KEY_DEVKEY; |
---|
415 | } |
---|
416 | return 1; |
---|
417 | } |
---|
418 | |
---|
419 | /* |
---|
420 | * Remove the key (no locking, for internal use). |
---|
421 | */ |
---|
422 | static int |
---|
423 | _ieee80211_crypto_delkey(struct ieee80211vap *vap, struct ieee80211_key *key) |
---|
424 | { |
---|
425 | KASSERT(key->wk_cipher != NULL, ("No cipher!")); |
---|
426 | |
---|
427 | IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, |
---|
428 | "%s: %s keyix %u flags 0x%x rsc %ju tsc %ju len %u\n", |
---|
429 | __func__, key->wk_cipher->ic_name, |
---|
430 | key->wk_keyix, key->wk_flags, |
---|
431 | key->wk_keyrsc[IEEE80211_NONQOS_TID], key->wk_keytsc, |
---|
432 | key->wk_keylen); |
---|
433 | |
---|
434 | if (key->wk_flags & IEEE80211_KEY_DEVKEY) { |
---|
435 | /* |
---|
436 | * Remove hardware entry. |
---|
437 | */ |
---|
438 | /* XXX key cache */ |
---|
439 | if (!dev_key_delete(vap, key)) { |
---|
440 | IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, |
---|
441 | "%s: driver did not delete key index %u\n", |
---|
442 | __func__, key->wk_keyix); |
---|
443 | vap->iv_stats.is_crypto_delkey++; |
---|
444 | /* XXX recovery? */ |
---|
445 | } |
---|
446 | } |
---|
447 | cipher_detach(key); |
---|
448 | memset(key, 0, sizeof(*key)); |
---|
449 | ieee80211_crypto_resetkey(vap, key, IEEE80211_KEYIX_NONE); |
---|
450 | return 1; |
---|
451 | } |
---|
452 | |
---|
453 | /* |
---|
454 | * Remove the specified key. |
---|
455 | */ |
---|
456 | int |
---|
457 | ieee80211_crypto_delkey(struct ieee80211vap *vap, struct ieee80211_key *key) |
---|
458 | { |
---|
459 | int status; |
---|
460 | |
---|
461 | ieee80211_key_update_begin(vap); |
---|
462 | status = _ieee80211_crypto_delkey(vap, key); |
---|
463 | ieee80211_key_update_end(vap); |
---|
464 | return status; |
---|
465 | } |
---|
466 | |
---|
467 | /* |
---|
468 | * Clear the global key table. |
---|
469 | */ |
---|
470 | void |
---|
471 | ieee80211_crypto_delglobalkeys(struct ieee80211vap *vap) |
---|
472 | { |
---|
473 | int i; |
---|
474 | |
---|
475 | ieee80211_key_update_begin(vap); |
---|
476 | for (i = 0; i < IEEE80211_WEP_NKID; i++) |
---|
477 | (void) _ieee80211_crypto_delkey(vap, &vap->iv_nw_keys[i]); |
---|
478 | ieee80211_key_update_end(vap); |
---|
479 | } |
---|
480 | |
---|
481 | /* |
---|
482 | * Set the contents of the specified key. |
---|
483 | * |
---|
484 | * Locking must be handled by the caller using: |
---|
485 | * ieee80211_key_update_begin(vap); |
---|
486 | * ieee80211_key_update_end(vap); |
---|
487 | */ |
---|
488 | int |
---|
489 | ieee80211_crypto_setkey(struct ieee80211vap *vap, struct ieee80211_key *key) |
---|
490 | { |
---|
491 | const struct ieee80211_cipher *cip = key->wk_cipher; |
---|
492 | |
---|
493 | KASSERT(cip != NULL, ("No cipher!")); |
---|
494 | |
---|
495 | IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, |
---|
496 | "%s: %s keyix %u flags 0x%x mac %s rsc %ju tsc %ju len %u\n", |
---|
497 | __func__, cip->ic_name, key->wk_keyix, |
---|
498 | key->wk_flags, ether_sprintf(key->wk_macaddr), |
---|
499 | key->wk_keyrsc[IEEE80211_NONQOS_TID], key->wk_keytsc, |
---|
500 | key->wk_keylen); |
---|
501 | |
---|
502 | if ((key->wk_flags & IEEE80211_KEY_DEVKEY) == 0) { |
---|
503 | /* XXX nothing allocated, should not happen */ |
---|
504 | IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, |
---|
505 | "%s: no device key setup done; should not happen!\n", |
---|
506 | __func__); |
---|
507 | vap->iv_stats.is_crypto_setkey_nokey++; |
---|
508 | return 0; |
---|
509 | } |
---|
510 | /* |
---|
511 | * Give cipher a chance to validate key contents. |
---|
512 | * XXX should happen before modifying state. |
---|
513 | */ |
---|
514 | if (!cip->ic_setkey(key)) { |
---|
515 | IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, |
---|
516 | "%s: cipher %s rejected key index %u len %u flags 0x%x\n", |
---|
517 | __func__, cip->ic_name, key->wk_keyix, |
---|
518 | key->wk_keylen, key->wk_flags); |
---|
519 | vap->iv_stats.is_crypto_setkey_cipher++; |
---|
520 | return 0; |
---|
521 | } |
---|
522 | return dev_key_set(vap, key); |
---|
523 | } |
---|
524 | |
---|
525 | /* |
---|
526 | * Return index if the key is a WEP key (0..3); -1 otherwise. |
---|
527 | * |
---|
528 | * This is different to "get_keyid" which defaults to returning |
---|
529 | * 0 for unicast keys; it assumes that it won't be used for WEP. |
---|
530 | */ |
---|
531 | int |
---|
532 | ieee80211_crypto_get_key_wepidx(const struct ieee80211vap *vap, |
---|
533 | const struct ieee80211_key *k) |
---|
534 | { |
---|
535 | |
---|
536 | if (k >= &vap->iv_nw_keys[0] && |
---|
537 | k < &vap->iv_nw_keys[IEEE80211_WEP_NKID]) |
---|
538 | return (k - vap->iv_nw_keys); |
---|
539 | return (-1); |
---|
540 | } |
---|
541 | |
---|
542 | /* |
---|
543 | * Note: only supports a single unicast key (0). |
---|
544 | */ |
---|
545 | uint8_t |
---|
546 | ieee80211_crypto_get_keyid(struct ieee80211vap *vap, struct ieee80211_key *k) |
---|
547 | { |
---|
548 | if (k >= &vap->iv_nw_keys[0] && |
---|
549 | k < &vap->iv_nw_keys[IEEE80211_WEP_NKID]) |
---|
550 | return (k - vap->iv_nw_keys); |
---|
551 | else |
---|
552 | return (0); |
---|
553 | } |
---|
554 | |
---|
555 | struct ieee80211_key * |
---|
556 | ieee80211_crypto_get_txkey(struct ieee80211_node *ni, struct mbuf *m) |
---|
557 | { |
---|
558 | struct ieee80211vap *vap = ni->ni_vap; |
---|
559 | struct ieee80211_frame *wh; |
---|
560 | |
---|
561 | /* |
---|
562 | * Multicast traffic always uses the multicast key. |
---|
563 | * Otherwise if a unicast key is set we use that and |
---|
564 | * it is always key index 0. When no unicast key is |
---|
565 | * set we fall back to the default transmit key. |
---|
566 | */ |
---|
567 | wh = mtod(m, struct ieee80211_frame *); |
---|
568 | if (IEEE80211_IS_MULTICAST(wh->i_addr1) || |
---|
569 | IEEE80211_KEY_UNDEFINED(&ni->ni_ucastkey)) { |
---|
570 | if (vap->iv_def_txkey == IEEE80211_KEYIX_NONE) { |
---|
571 | IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, |
---|
572 | wh->i_addr1, |
---|
573 | "no default transmit key (%s) deftxkey %u", |
---|
574 | __func__, vap->iv_def_txkey); |
---|
575 | vap->iv_stats.is_tx_nodefkey++; |
---|
576 | return NULL; |
---|
577 | } |
---|
578 | return &vap->iv_nw_keys[vap->iv_def_txkey]; |
---|
579 | } |
---|
580 | |
---|
581 | return &ni->ni_ucastkey; |
---|
582 | } |
---|
583 | |
---|
584 | /* |
---|
585 | * Add privacy headers appropriate for the specified key. |
---|
586 | */ |
---|
587 | struct ieee80211_key * |
---|
588 | ieee80211_crypto_encap(struct ieee80211_node *ni, struct mbuf *m) |
---|
589 | { |
---|
590 | struct ieee80211_key *k; |
---|
591 | const struct ieee80211_cipher *cip; |
---|
592 | |
---|
593 | if ((k = ieee80211_crypto_get_txkey(ni, m)) != NULL) { |
---|
594 | cip = k->wk_cipher; |
---|
595 | return (cip->ic_encap(k, m) ? k : NULL); |
---|
596 | } |
---|
597 | |
---|
598 | return NULL; |
---|
599 | } |
---|
600 | |
---|
601 | /* |
---|
602 | * Validate and strip privacy headers (and trailer) for a |
---|
603 | * received frame that has the WEP/Privacy bit set. |
---|
604 | */ |
---|
605 | int |
---|
606 | ieee80211_crypto_decap(struct ieee80211_node *ni, struct mbuf *m, int hdrlen, |
---|
607 | struct ieee80211_key **key) |
---|
608 | { |
---|
609 | #define IEEE80211_WEP_HDRLEN (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN) |
---|
610 | #define IEEE80211_WEP_MINLEN \ |
---|
611 | (sizeof(struct ieee80211_frame) + \ |
---|
612 | IEEE80211_WEP_HDRLEN + IEEE80211_WEP_CRCLEN) |
---|
613 | struct ieee80211vap *vap = ni->ni_vap; |
---|
614 | struct ieee80211_key *k; |
---|
615 | struct ieee80211_frame *wh; |
---|
616 | const struct ieee80211_rx_stats *rxs; |
---|
617 | const struct ieee80211_cipher *cip; |
---|
618 | uint8_t keyid; |
---|
619 | |
---|
620 | /* |
---|
621 | * Check for hardware decryption and IV stripping. |
---|
622 | * If the IV is stripped then we definitely can't find a key. |
---|
623 | * Set the key to NULL but return true; upper layers |
---|
624 | * will need to handle a NULL key for a successful |
---|
625 | * decrypt. |
---|
626 | */ |
---|
627 | rxs = ieee80211_get_rx_params_ptr(m); |
---|
628 | if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_DECRYPTED)) { |
---|
629 | if (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP) { |
---|
630 | /* |
---|
631 | * Hardware decrypted, IV stripped. |
---|
632 | * We can't find a key with a stripped IV. |
---|
633 | * Return successful. |
---|
634 | */ |
---|
635 | *key = NULL; |
---|
636 | return (1); |
---|
637 | } |
---|
638 | } |
---|
639 | |
---|
640 | /* NB: this minimum size data frame could be bigger */ |
---|
641 | if (m->m_pkthdr.len < IEEE80211_WEP_MINLEN) { |
---|
642 | IEEE80211_DPRINTF(vap, IEEE80211_MSG_ANY, |
---|
643 | "%s: WEP data frame too short, len %u\n", |
---|
644 | __func__, m->m_pkthdr.len); |
---|
645 | vap->iv_stats.is_rx_tooshort++; /* XXX need unique stat? */ |
---|
646 | *key = NULL; |
---|
647 | return (0); |
---|
648 | } |
---|
649 | |
---|
650 | /* |
---|
651 | * Locate the key. If unicast and there is no unicast |
---|
652 | * key then we fall back to the key id in the header. |
---|
653 | * This assumes unicast keys are only configured when |
---|
654 | * the key id in the header is meaningless (typically 0). |
---|
655 | */ |
---|
656 | wh = mtod(m, struct ieee80211_frame *); |
---|
657 | m_copydata(m, hdrlen + IEEE80211_WEP_IVLEN, sizeof(keyid), &keyid); |
---|
658 | if (IEEE80211_IS_MULTICAST(wh->i_addr1) || |
---|
659 | IEEE80211_KEY_UNDEFINED(&ni->ni_ucastkey)) |
---|
660 | k = &vap->iv_nw_keys[keyid >> 6]; |
---|
661 | else |
---|
662 | k = &ni->ni_ucastkey; |
---|
663 | |
---|
664 | /* |
---|
665 | * Insure crypto header is contiguous for all decap work. |
---|
666 | */ |
---|
667 | cip = k->wk_cipher; |
---|
668 | if (m->m_len < hdrlen + cip->ic_header && |
---|
669 | (m = m_pullup(m, hdrlen + cip->ic_header)) == NULL) { |
---|
670 | IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2, |
---|
671 | "unable to pullup %s header", cip->ic_name); |
---|
672 | vap->iv_stats.is_rx_wepfail++; /* XXX */ |
---|
673 | *key = NULL; |
---|
674 | return (0); |
---|
675 | } |
---|
676 | |
---|
677 | /* |
---|
678 | * Attempt decryption. |
---|
679 | * |
---|
680 | * If we fail then don't return the key - return NULL |
---|
681 | * and an error. |
---|
682 | */ |
---|
683 | if (cip->ic_decap(k, m, hdrlen)) { |
---|
684 | /* success */ |
---|
685 | *key = k; |
---|
686 | return (1); |
---|
687 | } |
---|
688 | |
---|
689 | /* Failure */ |
---|
690 | *key = NULL; |
---|
691 | return (0); |
---|
692 | #undef IEEE80211_WEP_MINLEN |
---|
693 | #undef IEEE80211_WEP_HDRLEN |
---|
694 | } |
---|
695 | |
---|
696 | /* |
---|
697 | * Check and remove any MIC. |
---|
698 | */ |
---|
699 | int |
---|
700 | ieee80211_crypto_demic(struct ieee80211vap *vap, struct ieee80211_key *k, |
---|
701 | struct mbuf *m, int force) |
---|
702 | { |
---|
703 | const struct ieee80211_cipher *cip; |
---|
704 | const struct ieee80211_rx_stats *rxs; |
---|
705 | struct ieee80211_frame *wh; |
---|
706 | |
---|
707 | rxs = ieee80211_get_rx_params_ptr(m); |
---|
708 | wh = mtod(m, struct ieee80211_frame *); |
---|
709 | |
---|
710 | /* |
---|
711 | * Handle demic / mic errors from hardware-decrypted offload devices. |
---|
712 | */ |
---|
713 | if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_DECRYPTED)) { |
---|
714 | if (rxs->c_pktflags & IEEE80211_RX_F_FAIL_MIC) { |
---|
715 | /* |
---|
716 | * Hardware has said MIC failed. We don't care about |
---|
717 | * whether it was stripped or not. |
---|
718 | * |
---|
719 | * Eventually - teach the demic methods in crypto |
---|
720 | * modules to handle a NULL key and not to dereference |
---|
721 | * it. |
---|
722 | */ |
---|
723 | ieee80211_notify_michael_failure(vap, wh, -1); |
---|
724 | return (0); |
---|
725 | } |
---|
726 | |
---|
727 | if (rxs->c_pktflags & IEEE80211_RX_F_MMIC_STRIP) { |
---|
728 | /* |
---|
729 | * Hardware has decrypted and not indicated a |
---|
730 | * MIC failure and has stripped the MIC. |
---|
731 | * We may not have a key, so for now just |
---|
732 | * return OK. |
---|
733 | */ |
---|
734 | return (1); |
---|
735 | } |
---|
736 | } |
---|
737 | |
---|
738 | /* |
---|
739 | * If we don't have a key at this point then we don't |
---|
740 | * have to demic anything. |
---|
741 | */ |
---|
742 | if (k == NULL) |
---|
743 | return (1); |
---|
744 | |
---|
745 | cip = k->wk_cipher; |
---|
746 | return (cip->ic_miclen > 0 ? cip->ic_demic(k, m, force) : 1); |
---|
747 | } |
---|
748 | |
---|
749 | |
---|
750 | static void |
---|
751 | load_ucastkey(void *arg, struct ieee80211_node *ni) |
---|
752 | { |
---|
753 | struct ieee80211vap *vap = ni->ni_vap; |
---|
754 | struct ieee80211_key *k; |
---|
755 | |
---|
756 | if (vap->iv_state != IEEE80211_S_RUN) |
---|
757 | return; |
---|
758 | k = &ni->ni_ucastkey; |
---|
759 | if (k->wk_flags & IEEE80211_KEY_DEVKEY) |
---|
760 | dev_key_set(vap, k); |
---|
761 | } |
---|
762 | |
---|
763 | /* |
---|
764 | * Re-load all keys known to the 802.11 layer that may |
---|
765 | * have hardware state backing them. This is used by |
---|
766 | * drivers on resume to push keys down into the device. |
---|
767 | */ |
---|
768 | void |
---|
769 | ieee80211_crypto_reload_keys(struct ieee80211com *ic) |
---|
770 | { |
---|
771 | struct ieee80211vap *vap; |
---|
772 | int i; |
---|
773 | |
---|
774 | /* |
---|
775 | * Keys in the global key table of each vap. |
---|
776 | */ |
---|
777 | /* NB: used only during resume so don't lock for now */ |
---|
778 | TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { |
---|
779 | if (vap->iv_state != IEEE80211_S_RUN) |
---|
780 | continue; |
---|
781 | for (i = 0; i < IEEE80211_WEP_NKID; i++) { |
---|
782 | const struct ieee80211_key *k = &vap->iv_nw_keys[i]; |
---|
783 | if (k->wk_flags & IEEE80211_KEY_DEVKEY) |
---|
784 | dev_key_set(vap, k); |
---|
785 | } |
---|
786 | } |
---|
787 | /* |
---|
788 | * Unicast keys. |
---|
789 | */ |
---|
790 | ieee80211_iterate_nodes(&ic->ic_sta, load_ucastkey, NULL); |
---|
791 | } |
---|
792 | |
---|
793 | /* |
---|
794 | * Set the default key index for WEP, or KEYIX_NONE for no default TX key. |
---|
795 | * |
---|
796 | * This should be done as part of a key update block (iv_key_update_begin / |
---|
797 | * iv_key_update_end.) |
---|
798 | */ |
---|
799 | void |
---|
800 | ieee80211_crypto_set_deftxkey(struct ieee80211vap *vap, ieee80211_keyix kid) |
---|
801 | { |
---|
802 | |
---|
803 | /* XXX TODO: assert we're in a key update block */ |
---|
804 | |
---|
805 | vap->iv_update_deftxkey(vap, kid); |
---|
806 | } |
---|