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