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