ieee80211_crypto_ccmp.c revision 1.14.2.2 1 /* $NetBSD: ieee80211_crypto_ccmp.c,v 1.14.2.2 2018/07/12 16:35:34 phil Exp $ */
2
3 /*-
4 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
5 *
6 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include <sys/cdefs.h>
31 #if __FreeBSD__
32 __FBSDID("$FreeBSD$");
33 #endif
34
35 /*
36 * IEEE 802.11i AES-CCMP crypto support.
37 *
38 * Part of this module is derived from similar code in the Host
39 * AP driver. The code is used with the consent of the author and
40 * it's license is included below.
41 */
42 #include "opt_wlan.h"
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/mbuf.h>
47 #include <sys/malloc.h>
48 #include <sys/kernel.h>
49 #include <sys/module.h>
50
51 #include <sys/socket.h>
52
53 #include <net/if.h>
54 #include <net/if_media.h>
55 #if __FreeBSD__
56 #include <net/ethernet.h>
57 #endif
58 #ifdef __NetBSD__
59 #include <net/route.h>
60 #endif
61
62 #include <net80211/ieee80211_var.h>
63
64 #include <crypto/rijndael/rijndael.h>
65
66 #ifdef __NetBSD__
67 #undef KASSERT
68 #define KASSERT(__cond, __complaint) FBSDKASSERT(__cond, __complaint)
69 #endif
70
71 #define AES_BLOCK_LEN 16
72
73 struct ccmp_ctx {
74 struct ieee80211vap *cc_vap; /* for diagnostics+statistics */
75 struct ieee80211com *cc_ic;
76 rijndael_ctx cc_aes;
77 };
78
79 static void *ccmp_attach(struct ieee80211vap *, struct ieee80211_key *);
80 static void ccmp_detach(struct ieee80211_key *);
81 static int ccmp_setkey(struct ieee80211_key *);
82 static void ccmp_setiv(struct ieee80211_key *, uint8_t *);
83 static int ccmp_encap(struct ieee80211_key *, struct mbuf *);
84 static int ccmp_decap(struct ieee80211_key *, struct mbuf *, int);
85 static int ccmp_enmic(struct ieee80211_key *, struct mbuf *, int);
86 static int ccmp_demic(struct ieee80211_key *, struct mbuf *, int);
87
88 static const struct ieee80211_cipher ccmp = {
89 .ic_name = "AES-CCM",
90 .ic_cipher = IEEE80211_CIPHER_AES_CCM,
91 .ic_header = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
92 IEEE80211_WEP_EXTIVLEN,
93 .ic_trailer = IEEE80211_WEP_MICLEN,
94 .ic_miclen = 0,
95 .ic_attach = ccmp_attach,
96 .ic_detach = ccmp_detach,
97 .ic_setkey = ccmp_setkey,
98 .ic_setiv = ccmp_setiv,
99 .ic_encap = ccmp_encap,
100 .ic_decap = ccmp_decap,
101 .ic_enmic = ccmp_enmic,
102 .ic_demic = ccmp_demic,
103 };
104
105 static int ccmp_encrypt(struct ieee80211_key *, struct mbuf *, int hdrlen);
106 static int ccmp_decrypt(struct ieee80211_key *, u_int64_t pn,
107 struct mbuf *, int hdrlen);
108
109 /* number of references from net80211 layer */
110 static int nrefs = 0;
111
112 static void *
113 ccmp_attach(struct ieee80211vap *vap, struct ieee80211_key *k)
114 {
115 struct ccmp_ctx *ctx;
116
117 ctx = (struct ccmp_ctx *) IEEE80211_MALLOC(sizeof(struct ccmp_ctx),
118 M_80211_CRYPTO, IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
119 if (ctx == NULL) {
120 vap->iv_stats.is_crypto_nomem++;
121 return NULL;
122 }
123 ctx->cc_vap = vap;
124 ctx->cc_ic = vap->iv_ic;
125 nrefs++; /* NB: we assume caller locking */
126 return ctx;
127 }
128
129 static void
130 ccmp_detach(struct ieee80211_key *k)
131 {
132 struct ccmp_ctx *ctx = k->wk_private;
133
134 IEEE80211_FREE(ctx, M_80211_CRYPTO);
135 KASSERT(nrefs > 0, ("imbalanced attach/detach"));
136 nrefs--; /* NB: we assume caller locking */
137 }
138
139 static int
140 ccmp_setkey(struct ieee80211_key *k)
141 {
142 struct ccmp_ctx *ctx = k->wk_private;
143
144 if (k->wk_keylen != (128/NBBY)) {
145 IEEE80211_DPRINTF(ctx->cc_vap, IEEE80211_MSG_CRYPTO,
146 "%s: Invalid key length %u, expecting %u\n",
147 __func__, k->wk_keylen, 128/NBBY);
148 return 0;
149 }
150 if (k->wk_flags & IEEE80211_KEY_SWENCRYPT)
151 rijndael_set_key(&ctx->cc_aes, k->wk_key, k->wk_keylen*NBBY);
152 return 1;
153 }
154
155 static void
156 ccmp_setiv(struct ieee80211_key *k, uint8_t *ivp)
157 {
158 struct ccmp_ctx *ctx = k->wk_private;
159 struct ieee80211vap *vap = ctx->cc_vap;
160 uint8_t keyid;
161
162 keyid = ieee80211_crypto_get_keyid(vap, k) << 6;
163
164 k->wk_keytsc++;
165 ivp[0] = k->wk_keytsc >> 0; /* PN0 */
166 ivp[1] = k->wk_keytsc >> 8; /* PN1 */
167 ivp[2] = 0; /* Reserved */
168 ivp[3] = keyid | IEEE80211_WEP_EXTIV; /* KeyID | ExtID */
169 ivp[4] = k->wk_keytsc >> 16; /* PN2 */
170 ivp[5] = k->wk_keytsc >> 24; /* PN3 */
171 ivp[6] = k->wk_keytsc >> 32; /* PN4 */
172 ivp[7] = k->wk_keytsc >> 40; /* PN5 */
173 }
174
175 /*
176 * Add privacy headers appropriate for the specified key.
177 */
178 static int
179 ccmp_encap(struct ieee80211_key *k, struct mbuf *m)
180 {
181 const struct ieee80211_frame *wh;
182 struct ccmp_ctx *ctx = k->wk_private;
183 struct ieee80211com *ic = ctx->cc_ic;
184 uint8_t *ivp;
185 int hdrlen;
186 int is_mgmt;
187
188 hdrlen = ieee80211_hdrspace(ic, mtod(m, void *));
189 wh = mtod(m, const struct ieee80211_frame *);
190 is_mgmt = IEEE80211_IS_MGMT(wh);
191
192 /*
193 * Check to see if we need to insert IV/MIC.
194 *
195 * Some offload devices don't require the IV to be inserted
196 * as part of the hardware encryption.
197 */
198 if (is_mgmt && (k->wk_flags & IEEE80211_KEY_NOIVMGT))
199 return 1;
200 if ((! is_mgmt) && (k->wk_flags & IEEE80211_KEY_NOIV))
201 return 1;
202
203 /*
204 * Copy down 802.11 header and add the IV, KeyID, and ExtIV.
205 */
206 M_PREPEND(m, ccmp.ic_header, M_NOWAIT);
207 if (m == NULL)
208 return 0;
209 ivp = mtod(m, uint8_t *);
210 ovbcopy(ivp + ccmp.ic_header, ivp, hdrlen);
211 ivp += hdrlen;
212
213 ccmp_setiv(k, ivp);
214
215 /*
216 * Finally, do software encrypt if needed.
217 */
218 if ((k->wk_flags & IEEE80211_KEY_SWENCRYPT) &&
219 !ccmp_encrypt(k, m, hdrlen))
220 return 0;
221
222 return 1;
223 }
224
225 /*
226 * Add MIC to the frame as needed.
227 */
228 static int
229 ccmp_enmic(struct ieee80211_key *k, struct mbuf *m, int force)
230 {
231
232 return 1;
233 }
234
235 static __inline uint64_t
236 READ_6(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5)
237 {
238 uint32_t iv32 = (b0 << 0) | (b1 << 8) | (b2 << 16) | (b3 << 24);
239 uint16_t iv16 = (b4 << 0) | (b5 << 8);
240 return (((uint64_t)iv16) << 32) | iv32;
241 }
242
243 /*
244 * Validate and strip privacy headers (and trailer) for a
245 * received frame. The specified key should be correct but
246 * is also verified.
247 */
248 static int
249 ccmp_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen)
250 {
251 const struct ieee80211_rx_stats *rxs;
252 struct ccmp_ctx *ctx = k->wk_private;
253 struct ieee80211vap *vap = ctx->cc_vap;
254 struct ieee80211_frame *wh;
255 uint8_t *ivp, tid;
256 uint64_t pn;
257
258 rxs = ieee80211_get_rx_params_ptr(m);
259
260 if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP))
261 goto finish;
262
263 /*
264 * Header should have extended IV and sequence number;
265 * verify the former and validate the latter.
266 */
267 wh = mtod(m, struct ieee80211_frame *);
268 ivp = mtod(m, uint8_t *) + hdrlen;
269 if ((ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV) == 0) {
270 /*
271 * No extended IV; discard frame.
272 */
273 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2,
274 "%s", "missing ExtIV for AES-CCM cipher");
275 vap->iv_stats.is_rx_ccmpformat++;
276 return 0;
277 }
278 tid = ieee80211_gettid(wh);
279 pn = READ_6(ivp[0], ivp[1], ivp[4], ivp[5], ivp[6], ivp[7]);
280 if (pn <= k->wk_keyrsc[tid] &&
281 (k->wk_flags & IEEE80211_KEY_NOREPLAY) == 0) {
282 /*
283 * Replay violation.
284 */
285 ieee80211_notify_replay_failure(vap, wh, k, pn, tid);
286 vap->iv_stats.is_rx_ccmpreplay++;
287 return 0;
288 }
289
290 /*
291 * Check if the device handled the decrypt in hardware.
292 * If so we just strip the header; otherwise we need to
293 * handle the decrypt in software. Note that for the
294 * latter we leave the header in place for use in the
295 * decryption work.
296 */
297 if ((k->wk_flags & IEEE80211_KEY_SWDECRYPT) &&
298 !ccmp_decrypt(k, pn, m, hdrlen))
299 return 0;
300
301 finish:
302 /*
303 * Copy up 802.11 header and strip crypto bits.
304 */
305 if (! ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP))) {
306 ovbcopy(mtod(m, void *), mtod(m, uint8_t *) + ccmp.ic_header,
307 hdrlen);
308 m_adj(m, ccmp.ic_header);
309 }
310
311 /*
312 * XXX TODO: see if MMIC_STRIP also covers CCMP MIC trailer.
313 */
314 if (! ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_MMIC_STRIP)))
315 m_adj(m, -ccmp.ic_trailer);
316
317 /*
318 * Ok to update rsc now.
319 */
320 if (! ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP))) {
321 k->wk_keyrsc[tid] = pn;
322 }
323
324 return 1;
325 }
326
327 /*
328 * Verify and strip MIC from the frame.
329 */
330 static int
331 ccmp_demic(struct ieee80211_key *k, struct mbuf *m, int force)
332 {
333 return 1;
334 }
335
336 static __inline void
337 xor_block(uint8_t *b, const uint8_t *a, size_t len)
338 {
339 int i;
340 for (i = 0; i < len; i++)
341 b[i] ^= a[i];
342 }
343
344 /*
345 * Host AP crypt: host-based CCMP encryption implementation for Host AP driver
346 *
347 * Copyright (c) 2003-2004, Jouni Malinen <jkmaline (at) cc.hut.fi>
348 *
349 * This program is free software; you can redistribute it and/or modify
350 * it under the terms of the GNU General Public License version 2 as
351 * published by the Free Software Foundation. See README and COPYING for
352 * more details.
353 *
354 * Alternatively, this software may be distributed under the terms of BSD
355 * license.
356 */
357
358 static void
359 ccmp_init_blocks(rijndael_ctx *ctx, struct ieee80211_frame *wh,
360 u_int64_t pn, size_t dlen,
361 uint8_t b0[AES_BLOCK_LEN], uint8_t aad[2 * AES_BLOCK_LEN],
362 uint8_t auth[AES_BLOCK_LEN], uint8_t s0[AES_BLOCK_LEN])
363 {
364 #define IS_QOS_DATA(wh) IEEE80211_QOS_HAS_SEQ(wh)
365
366 /* CCM Initial Block:
367 * Flag (Include authentication header, M=3 (8-octet MIC),
368 * L=1 (2-octet Dlen))
369 * Nonce: 0x00 | A2 | PN
370 * Dlen */
371 b0[0] = 0x59;
372 /* NB: b0[1] set below */
373 IEEE80211_ADDR_COPY(b0 + 2, wh->i_addr2);
374 b0[8] = pn >> 40;
375 b0[9] = pn >> 32;
376 b0[10] = pn >> 24;
377 b0[11] = pn >> 16;
378 b0[12] = pn >> 8;
379 b0[13] = pn >> 0;
380 b0[14] = (dlen >> 8) & 0xff;
381 b0[15] = dlen & 0xff;
382
383 /* AAD:
384 * FC with bits 4..6 and 11..13 masked to zero; 14 is always one
385 * A1 | A2 | A3
386 * SC with bits 4..15 (seq#) masked to zero
387 * A4 (if present)
388 * QC (if present)
389 */
390 aad[0] = 0; /* AAD length >> 8 */
391 /* NB: aad[1] set below */
392 aad[2] = wh->i_fc[0] & 0x8f; /* XXX magic #s */
393 aad[3] = wh->i_fc[1] & 0xc7; /* XXX magic #s */
394 /* NB: we know 3 addresses are contiguous */
395 memcpy(aad + 4, wh->i_addr1, 3 * IEEE80211_ADDR_LEN);
396 aad[22] = wh->i_seq[0] & IEEE80211_SEQ_FRAG_MASK;
397 aad[23] = 0; /* all bits masked */
398 /*
399 * Construct variable-length portion of AAD based
400 * on whether this is a 4-address frame/QOS frame.
401 * We always zero-pad to 32 bytes before running it
402 * through the cipher.
403 *
404 * We also fill in the priority bits of the CCM
405 * initial block as we know whether or not we have
406 * a QOS frame.
407 */
408 if (IEEE80211_IS_DSTODS(wh)) {
409 IEEE80211_ADDR_COPY(aad + 24,
410 ((struct ieee80211_frame_addr4 *)wh)->i_addr4);
411 if (IS_QOS_DATA(wh)) {
412 struct ieee80211_qosframe_addr4 *qwh4 =
413 (struct ieee80211_qosframe_addr4 *) wh;
414 aad[30] = qwh4->i_qos[0] & 0x0f;/* just priority bits */
415 aad[31] = 0;
416 b0[1] = aad[30];
417 aad[1] = 22 + IEEE80211_ADDR_LEN + 2;
418 } else {
419 *(uint16_t *)&aad[30] = 0;
420 b0[1] = 0;
421 aad[1] = 22 + IEEE80211_ADDR_LEN;
422 }
423 } else {
424 if (IS_QOS_DATA(wh)) {
425 struct ieee80211_qosframe *qwh =
426 (struct ieee80211_qosframe*) wh;
427 aad[24] = qwh->i_qos[0] & 0x0f; /* just priority bits */
428 aad[25] = 0;
429 b0[1] = aad[24];
430 aad[1] = 22 + 2;
431 } else {
432 *(uint16_t *)&aad[24] = 0;
433 b0[1] = 0;
434 aad[1] = 22;
435 }
436 *(uint16_t *)&aad[26] = 0;
437 *(uint32_t *)&aad[28] = 0;
438 }
439
440 /* Start with the first block and AAD */
441 rijndael_encrypt(ctx, b0, auth);
442 xor_block(auth, aad, AES_BLOCK_LEN);
443 rijndael_encrypt(ctx, auth, auth);
444 xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN);
445 rijndael_encrypt(ctx, auth, auth);
446 b0[0] &= 0x07;
447 b0[14] = b0[15] = 0;
448 rijndael_encrypt(ctx, b0, s0);
449 #undef IS_QOS_DATA
450 }
451
452 #define CCMP_ENCRYPT(_i, _b, _b0, _pos, _e, _len) do { \
453 /* Authentication */ \
454 xor_block(_b, _pos, _len); \
455 rijndael_encrypt(&ctx->cc_aes, _b, _b); \
456 /* Encryption, with counter */ \
457 _b0[14] = (_i >> 8) & 0xff; \
458 _b0[15] = _i & 0xff; \
459 rijndael_encrypt(&ctx->cc_aes, _b0, _e); \
460 xor_block(_pos, _e, _len); \
461 } while (0)
462
463 static int
464 ccmp_encrypt(struct ieee80211_key *key, struct mbuf *m0, int hdrlen)
465 {
466 struct ccmp_ctx *ctx = key->wk_private;
467 struct ieee80211_frame *wh;
468 struct mbuf *m = m0;
469 int data_len, i, space;
470 uint8_t aad[2 * AES_BLOCK_LEN], b0[AES_BLOCK_LEN], b[AES_BLOCK_LEN],
471 e[AES_BLOCK_LEN], s0[AES_BLOCK_LEN];
472 uint8_t *pos;
473
474 ctx->cc_vap->iv_stats.is_crypto_ccmp++;
475
476 wh = mtod(m, struct ieee80211_frame *);
477 data_len = m->m_pkthdr.len - (hdrlen + ccmp.ic_header);
478 ccmp_init_blocks(&ctx->cc_aes, wh, key->wk_keytsc,
479 data_len, b0, aad, b, s0);
480
481 i = 1;
482 pos = mtod(m, uint8_t *) + hdrlen + ccmp.ic_header;
483 /* NB: assumes header is entirely in first mbuf */
484 space = m->m_len - (hdrlen + ccmp.ic_header);
485 for (;;) {
486 if (space > data_len)
487 space = data_len;
488 /*
489 * Do full blocks.
490 */
491 while (space >= AES_BLOCK_LEN) {
492 CCMP_ENCRYPT(i, b, b0, pos, e, AES_BLOCK_LEN);
493 pos += AES_BLOCK_LEN, space -= AES_BLOCK_LEN;
494 data_len -= AES_BLOCK_LEN;
495 i++;
496 }
497 if (data_len <= 0) /* no more data */
498 break;
499 m = m->m_next;
500 if (m == NULL) { /* last buffer */
501 if (space != 0) {
502 /*
503 * Short last block.
504 */
505 CCMP_ENCRYPT(i, b, b0, pos, e, space);
506 }
507 break;
508 }
509 if (space != 0) {
510 uint8_t *pos_next;
511 int space_next;
512 int len, dl, sp;
513 struct mbuf *n;
514
515 /*
516 * Block straddles one or more mbufs, gather data
517 * into the block buffer b, apply the cipher, then
518 * scatter the results back into the mbuf chain.
519 * The buffer will automatically get space bytes
520 * of data at offset 0 copied in+out by the
521 * CCMP_ENCRYPT request so we must take care of
522 * the remaining data.
523 */
524 n = m;
525 dl = data_len;
526 sp = space;
527 for (;;) {
528 pos_next = mtod(n, uint8_t *);
529 len = min(dl, AES_BLOCK_LEN);
530 space_next = len > sp ? len - sp : 0;
531 if (n->m_len >= space_next) {
532 /*
533 * This mbuf has enough data; just grab
534 * what we need and stop.
535 */
536 xor_block(b+sp, pos_next, space_next);
537 break;
538 }
539 /*
540 * This mbuf's contents are insufficient,
541 * take 'em all and prepare to advance to
542 * the next mbuf.
543 */
544 xor_block(b+sp, pos_next, n->m_len);
545 sp += n->m_len, dl -= n->m_len;
546 n = n->m_next;
547 if (n == NULL)
548 break;
549 }
550
551 CCMP_ENCRYPT(i, b, b0, pos, e, space);
552
553 /* NB: just like above, but scatter data to mbufs */
554 dl = data_len;
555 sp = space;
556 for (;;) {
557 pos_next = mtod(m, uint8_t *);
558 len = min(dl, AES_BLOCK_LEN);
559 space_next = len > sp ? len - sp : 0;
560 if (m->m_len >= space_next) {
561 xor_block(pos_next, e+sp, space_next);
562 break;
563 }
564 xor_block(pos_next, e+sp, m->m_len);
565 sp += m->m_len, dl -= m->m_len;
566 m = m->m_next;
567 if (m == NULL)
568 goto done;
569 }
570 /*
571 * Do bookkeeping. m now points to the last mbuf
572 * we grabbed data from. We know we consumed a
573 * full block of data as otherwise we'd have hit
574 * the end of the mbuf chain, so deduct from data_len.
575 * Otherwise advance the block number (i) and setup
576 * pos+space to reflect contents of the new mbuf.
577 */
578 data_len -= AES_BLOCK_LEN;
579 i++;
580 pos = pos_next + space_next;
581 space = m->m_len - space_next;
582 } else {
583 /*
584 * Setup for next buffer.
585 */
586 pos = mtod(m, uint8_t *);
587 space = m->m_len;
588 }
589 }
590 done:
591 /* tack on MIC */
592 xor_block(b, s0, ccmp.ic_trailer);
593 return m_append(m0, ccmp.ic_trailer, b);
594 }
595 #undef CCMP_ENCRYPT
596
597 #define CCMP_DECRYPT(_i, _b, _b0, _pos, _a, _len) do { \
598 /* Decrypt, with counter */ \
599 _b0[14] = (_i >> 8) & 0xff; \
600 _b0[15] = _i & 0xff; \
601 rijndael_encrypt(&ctx->cc_aes, _b0, _b); \
602 xor_block(_pos, _b, _len); \
603 /* Authentication */ \
604 xor_block(_a, _pos, _len); \
605 rijndael_encrypt(&ctx->cc_aes, _a, _a); \
606 } while (0)
607
608 static int
609 ccmp_decrypt(struct ieee80211_key *key, u_int64_t pn, struct mbuf *m, int hdrlen)
610 {
611 struct ccmp_ctx *ctx = key->wk_private;
612 struct ieee80211vap *vap = ctx->cc_vap;
613 struct ieee80211_frame *wh;
614 uint8_t aad[2 * AES_BLOCK_LEN];
615 uint8_t b0[AES_BLOCK_LEN], b[AES_BLOCK_LEN], a[AES_BLOCK_LEN];
616 uint8_t mic[AES_BLOCK_LEN];
617 size_t data_len;
618 int i;
619 uint8_t *pos;
620 u_int space;
621
622 ctx->cc_vap->iv_stats.is_crypto_ccmp++;
623
624 wh = mtod(m, struct ieee80211_frame *);
625 data_len = m->m_pkthdr.len - (hdrlen + ccmp.ic_header + ccmp.ic_trailer);
626 ccmp_init_blocks(&ctx->cc_aes, wh, pn, data_len, b0, aad, a, b);
627 m_copydata(m, m->m_pkthdr.len - ccmp.ic_trailer, ccmp.ic_trailer, mic);
628 xor_block(mic, b, ccmp.ic_trailer);
629
630 i = 1;
631 pos = mtod(m, uint8_t *) + hdrlen + ccmp.ic_header;
632 space = m->m_len - (hdrlen + ccmp.ic_header);
633 for (;;) {
634 if (space > data_len)
635 space = data_len;
636 while (space >= AES_BLOCK_LEN) {
637 CCMP_DECRYPT(i, b, b0, pos, a, AES_BLOCK_LEN);
638 pos += AES_BLOCK_LEN, space -= AES_BLOCK_LEN;
639 data_len -= AES_BLOCK_LEN;
640 i++;
641 }
642 if (data_len <= 0) /* no more data */
643 break;
644 m = m->m_next;
645 if (m == NULL) { /* last buffer */
646 if (space != 0) /* short last block */
647 CCMP_DECRYPT(i, b, b0, pos, a, space);
648 break;
649 }
650 if (space != 0) {
651 uint8_t *pos_next;
652 u_int space_next;
653 u_int len;
654
655 /*
656 * Block straddles buffers, split references. We
657 * do not handle splits that require >2 buffers
658 * since rx'd frames are never badly fragmented
659 * because drivers typically recv in clusters.
660 */
661 pos_next = mtod(m, uint8_t *);
662 len = min(data_len, AES_BLOCK_LEN);
663 space_next = len > space ? len - space : 0;
664 KASSERT(m->m_len >= space_next,
665 ("not enough data in following buffer, "
666 "m_len %u need %u\n", m->m_len, space_next));
667
668 xor_block(b+space, pos_next, space_next);
669 CCMP_DECRYPT(i, b, b0, pos, a, space);
670 xor_block(pos_next, b+space, space_next);
671 data_len -= len;
672 i++;
673
674 pos = pos_next + space_next;
675 space = m->m_len - space_next;
676 } else {
677 /*
678 * Setup for next buffer.
679 */
680 pos = mtod(m, uint8_t *);
681 space = m->m_len;
682 }
683 }
684 if (memcmp(mic, a, ccmp.ic_trailer) != 0) {
685 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2,
686 "%s", "AES-CCM decrypt failed; MIC mismatch");
687 vap->iv_stats.is_rx_ccmpmic++;
688 return 0;
689 }
690 return 1;
691 }
692 #undef CCMP_DECRYPT
693
694 /*
695 * Module glue.
696 */
697 IEEE80211_CRYPTO_MODULE(ccmp, 1);
698