[svn-upgrade] new version madwifi (0.9.4+r4133.20100922)
[debian/madwifi.git] / net80211 / ieee80211_crypto_ccmp.c
1 /*-
2  * Copyright (c) 2002-2005 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  * 3. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * Alternatively, this software may be distributed under the terms of the
17  * GNU General Public License ("GPL") version 2 as published by the Free
18  * Software Foundation.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  * $Id: ieee80211_crypto_ccmp.c 4126 2010-03-23 22:50:36Z proski $
32  */
33
34 /*
35  * IEEE 802.11i AES-CCMP crypto support.
36  *
37  * Part of this module is derived from similar code in the Host
38  * AP driver. The code is used with the consent of the author and
39  * it's license is included below.
40  */
41 #ifndef AUTOCONF_INCLUDED
42 #include <linux/config.h>
43 #endif
44 #include <linux/version.h>
45 #include <linux/module.h>
46 #include <linux/skbuff.h>
47 #include <linux/netdevice.h>
48 #include <linux/random.h>
49 #include <linux/init.h>
50
51 #include <linux/crypto.h>
52 #include <asm/scatterlist.h>
53
54 #include "if_media.h"
55
56 #include <net80211/ieee80211_var.h>
57
58 #define AES_BLOCK_LEN 16
59
60 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
61 #define crypto_cipher crypto_tfm
62 #define crypto_alloc_cipher(name,type,mask) crypto_alloc_tfm(name,type)
63 #define crypto_free_cipher(cipher) crypto_free_tfm(cipher)
64 #endif
65
66 struct ccmp_ctx {
67         struct ieee80211vap *cc_vap;    /* for diagnostics + statistics */
68         struct ieee80211com *cc_ic;
69         struct crypto_cipher *cc_tfm;
70 };
71
72 static void *ccmp_attach(struct ieee80211vap *, struct ieee80211_key *);
73 static void ccmp_detach(struct ieee80211_key *);
74 static int ccmp_setkey(struct ieee80211_key *);
75 static int ccmp_encap(struct ieee80211_key *, struct sk_buff *, u_int8_t);
76 static int ccmp_decap(struct ieee80211_key *, struct sk_buff *, int);
77 static int ccmp_enmic(struct ieee80211_key *, struct sk_buff *, int);
78 static int ccmp_demic(struct ieee80211_key *, struct sk_buff *, int);
79
80 static const struct ieee80211_cipher ccmp = {
81         .ic_name        = "AES-CCM",
82         .ic_cipher      = IEEE80211_CIPHER_AES_CCM,
83         .ic_header      = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
84                           IEEE80211_WEP_EXTIVLEN,
85         .ic_trailer     = IEEE80211_WEP_MICLEN,
86         .ic_miclen      = 0,
87         .ic_attach      = ccmp_attach,
88         .ic_detach      = ccmp_detach,
89         .ic_setkey      = ccmp_setkey,
90         .ic_encap       = ccmp_encap,
91         .ic_decap       = ccmp_decap,
92         .ic_enmic       = ccmp_enmic,
93         .ic_demic       = ccmp_demic,
94 };
95
96 static int ccmp_encrypt(struct ieee80211_key *, struct sk_buff *, int);
97 static int ccmp_decrypt(struct ieee80211_key *, u_int64_t, struct sk_buff *, int);
98
99 static void *
100 ccmp_attach(struct ieee80211vap *vap, struct ieee80211_key *k)
101 {
102         struct ccmp_ctx *ctx;
103
104         _MOD_INC_USE(THIS_MODULE, return NULL);
105
106         MALLOC(ctx, struct ccmp_ctx *, sizeof(struct ccmp_ctx),
107                 M_DEVBUF, M_NOWAIT | M_ZERO);
108         if (ctx == NULL) {
109                 vap->iv_stats.is_crypto_nomem++;
110                 _MOD_DEC_USE(THIS_MODULE);
111                 return NULL;
112         }
113
114         ctx->cc_vap = vap;
115         ctx->cc_ic = vap->iv_ic;
116         return ctx;
117 }
118
119 static void
120 ccmp_detach(struct ieee80211_key *k)
121 {
122         struct ccmp_ctx *ctx = k->wk_private;
123
124         if (ctx->cc_tfm != NULL)
125                 crypto_free_cipher(ctx->cc_tfm);
126         FREE(ctx, M_DEVBUF);
127
128         _MOD_DEC_USE(THIS_MODULE);
129 }
130
131 static int
132 ccmp_setkey(struct ieee80211_key *k)
133 {
134         struct ccmp_ctx *ctx = k->wk_private;
135
136         if (k->wk_keylen != (128 / NBBY)) {
137                 IEEE80211_DPRINTF(ctx->cc_vap, IEEE80211_MSG_CRYPTO,
138                         "%s: Invalid key length %u, expecting %u\n",
139                         __func__, k->wk_keylen, 128 / NBBY);
140                 return 0;
141         }
142         
143         if (k->wk_flags & IEEE80211_KEY_SWCRYPT) {
144                 if (ctx->cc_tfm == NULL)
145                         ctx->cc_tfm = crypto_alloc_cipher("aes", 0,
146                                                           CRYPTO_ALG_ASYNC);
147                 
148                 if (ctx->cc_tfm == NULL) {
149                         IEEE80211_DPRINTF(ctx->cc_vap, IEEE80211_MSG_CRYPTO,
150                                 "%s: Tried to add a software crypto key, but software crypto not available\n",
151                                 __func__);
152                         return 0;
153                 }
154                 
155                 crypto_cipher_setkey(ctx->cc_tfm, k->wk_key, k->wk_keylen);
156         }
157         return 1;
158 }
159
160 /*
161  * Add privacy headers appropriate for the specified key.
162  */
163 static int
164 ccmp_encap(struct ieee80211_key *k, struct sk_buff *skb, u_int8_t keyid)
165 {
166         struct ccmp_ctx *ctx = k->wk_private;
167         struct ieee80211com *ic = ctx->cc_ic;
168         u_int8_t *ivp;
169         int hdrlen;
170
171         hdrlen = ieee80211_hdrspace(ic, skb->data);
172
173         /*
174          * Copy down 802.11 header and add the IV, KeyID, and ExtIV.
175          */
176         ivp = skb_push(skb, ccmp.ic_header);
177         memmove(ivp, ivp + ccmp.ic_header, hdrlen);
178         ivp += hdrlen;
179
180         k->wk_keytsc++;         /* XXX wrap at 48 bits */
181         ivp[0] = k->wk_keytsc >> 0;             /* PN0 */
182         ivp[1] = k->wk_keytsc >> 8;             /* PN1 */
183         ivp[2] = 0;                             /* Reserved */
184         ivp[3] = keyid | IEEE80211_WEP_EXTIV;   /* KeyID | ExtID */
185         ivp[4] = k->wk_keytsc >> 16;            /* PN2 */
186         ivp[5] = k->wk_keytsc >> 24;            /* PN3 */
187         ivp[6] = k->wk_keytsc >> 32;            /* PN4 */
188         ivp[7] = k->wk_keytsc >> 40;            /* PN5 */
189
190         /*
191          * Finally, do software encrypt if needed.
192          */
193         if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) &&
194             !ccmp_encrypt(k, skb, hdrlen))
195                 return 0;
196
197         return 1;
198 }
199
200 /*
201  * Add MIC to the frame as needed.
202  */
203 static int
204 ccmp_enmic(struct ieee80211_key *k, struct sk_buff *skb, int force)
205 {
206         return 1;
207 }
208
209 static __inline uint64_t
210 READ_6(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5)
211 {
212         uint32_t iv32 = (b0 << 0) | (b1 << 8) | (b2 << 16) | (b3 << 24);
213         uint16_t iv16 = (b4 << 0) | (b5 << 8);
214         return (((uint64_t)iv16) << 32) | iv32;
215 }
216
217 /*
218  * Validate and strip privacy headers (and trailer) for a
219  * received frame. The specified key should be correct but
220  * is also verified.
221  */
222 static int
223 ccmp_decap(struct ieee80211_key *k, struct sk_buff *skb, int hdrlen)
224 {
225         struct ccmp_ctx *ctx = k->wk_private;
226         struct ieee80211vap *vap = ctx->cc_vap;
227         struct ieee80211_frame *wh;
228         uint8_t *ivp;
229         uint64_t pn;
230         u_int8_t tid;
231
232         /*
233          * Header should have extended IV and sequence number;
234          * verify the former and validate the latter.
235          */
236         wh = (struct ieee80211_frame *)skb->data;
237         ivp = skb->data + hdrlen;
238         if ((ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV) == 0) {
239                 /*
240                  * No extended IV; discard frame.
241                  */
242                 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2,
243                         "%s", "Missing ExtIV for AES-CCM cipher");
244                 vap->iv_stats.is_rx_ccmpformat++;
245                 return 0;
246         }
247         tid = 0;
248         if (IEEE80211_QOS_HAS_SEQ(wh)) 
249                 tid = ((struct ieee80211_qosframe *)wh)->i_qos[0] & IEEE80211_QOS_TID;
250         /* NB: assume IEEE80211_WEP_MINLEN covers the extended IV */ 
251         pn = READ_6(ivp[0], ivp[1], ivp[4], ivp[5], ivp[6], ivp[7]);
252         if (pn <= k->wk_keyrsc[tid]) {
253                 /*
254                  * Replay violation.
255                  */
256                 ieee80211_notify_replay_failure(vap, wh, k, pn);
257                 vap->iv_stats.is_rx_ccmpreplay++;
258                 return 0;
259         }
260
261         /*
262          * Check if the device handled the decrypt in hardware.
263          * If so we just strip the header; otherwise we need to
264          * handle the decrypt in software.  Note that for the
265          * latter we leave the header in place for use in the
266          * decryption work.
267          */
268         if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) &&
269             !ccmp_decrypt(k, pn, skb, hdrlen))
270                 return 0;
271
272         /*
273          * Copy up 802.11 header and strip crypto bits.
274          */
275         memmove(skb->data + ccmp.ic_header, skb->data, hdrlen);
276         skb_pull(skb, ccmp.ic_header);
277         while (skb->next != NULL)
278                 skb = skb->next;
279         skb_trim(skb, skb->len - ccmp.ic_trailer);
280
281         /*
282          * Ok to update rsc now.
283          */
284         k->wk_keyrsc[tid] = pn;
285
286         return 1;
287 }
288
289 /*
290  * Verify and strip MIC from the frame.
291  */
292 static int
293 ccmp_demic(struct ieee80211_key *k, struct sk_buff *skb, int hdrlen)
294 {
295         return 1;
296 }
297
298 static __inline void
299 xor_block(u8 *b, const u8 *a, size_t len)
300 {
301         int i;
302         for (i = 0; i < len; i++)
303                 b[i] ^= a[i];
304 }
305
306 static void
307 rijndael_encrypt(struct crypto_cipher *tfm, const void *src, void *dst)
308 {
309 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
310         crypto_cipher_encrypt_one(tfm, dst, src);
311 #else
312         struct scatterlist sg_src;
313         struct scatterlist sg_dst;
314
315         sg_src.page = virt_to_page(src);
316         sg_src.offset = offset_in_page(src);
317         sg_src.length = AES_BLOCK_LEN;
318
319         sg_dst.page = virt_to_page(dst);
320         sg_dst.offset = offset_in_page(dst);
321         sg_dst.length = AES_BLOCK_LEN;
322         crypto_cipher_encrypt(tfm, &sg_dst, &sg_src, AES_BLOCK_LEN);
323 #endif
324 }
325
326 /*
327  * Host AP crypt: host-based CCMP encryption implementation for Host AP driver
328  *
329  * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
330  *
331  * This program is free software; you can redistribute it and/or modify
332  * it under the terms of the GNU General Public License version 2 as
333  * published by the Free Software Foundation. See README and COPYING for
334  * more details.
335  *
336  * Alternatively, this software may be distributed under the terms of BSD
337  * license.
338  */
339
340 static void
341 ccmp_init_blocks(struct crypto_cipher *tfm, struct ieee80211_frame *wh,
342         u_int64_t pn, size_t dlen,
343         uint8_t b0[AES_BLOCK_LEN], uint8_t aad[2 * AES_BLOCK_LEN],
344         uint8_t auth[AES_BLOCK_LEN], uint8_t s0[AES_BLOCK_LEN])
345 {
346 #define IS_4ADDRESS(wh) \
347         ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
348 #define IS_QOS_DATA(wh) IEEE80211_QOS_HAS_SEQ(wh)
349
350         /* CCM Initial Block:
351          * Flag (Include authentication header, M=3 (8-octet MIC),
352          *       L=1 (2-octet Dlen))
353          * Nonce: 0x00 | A2 | PN
354          * Dlen */
355         b0[0] = 0x59;
356         /* NB: b0[1] set below */
357         IEEE80211_ADDR_COPY(b0 + 2, wh->i_addr2);
358         b0[8] = pn >> 40;
359         b0[9] = pn >> 32;
360         b0[10] = pn >> 24;
361         b0[11] = pn >> 16;
362         b0[12] = pn >> 8;
363         b0[13] = pn >> 0;
364         b0[14] = (dlen >> 8) & 0xff;
365         b0[15] = dlen & 0xff;
366
367         /* AAD:
368          * FC with bits 4..6 and 11..13 masked to zero; 14 is always one
369          * A1 | A2 | A3
370          * SC with bits 4..15 (seq#) masked to zero
371          * A4 (if present)
372          * QC (if present)
373          */
374         aad[0] = 0;     /* AAD length >> 8 */
375         /* NB: aad[1] set below */
376         aad[2] = wh->i_fc[0] & 0x8f;    /* XXX magic #s */
377         aad[3] = wh->i_fc[1] & 0xc7;    /* XXX magic #s */
378         /* NB: we know 3 addresses are contiguous */
379         memcpy(aad + 4, wh->i_addr1, 3 * IEEE80211_ADDR_LEN);
380         aad[22] = wh->i_seq[0] & IEEE80211_SEQ_FRAG_MASK;
381         aad[23] = 0; /* all bits masked */
382         /*
383          * Construct variable-length portion of AAD based
384          * on whether this is a 4-address frame/QOS frame.
385          * We always zero-pad to 32 bytes before running it
386          * through the cipher.
387          *
388          * We also fill in the priority bits of the CCM
389          * initial block as we know whether or not we have
390          * a QOS frame.
391          */
392         if (IS_4ADDRESS(wh)) {
393                 IEEE80211_ADDR_COPY(aad + 24,
394                         ((struct ieee80211_frame_addr4 *)wh)->i_addr4);
395                 if (IS_QOS_DATA(wh)) {
396                         struct ieee80211_qosframe_addr4 *qwh4 =
397                                 (struct ieee80211_qosframe_addr4 *) wh;
398                         aad[30] = qwh4->i_qos[0] & 0x0f;/* just priority bits */
399                         aad[31] = 0;
400                         b0[1] = aad[30];
401                         aad[1] = 22 + IEEE80211_ADDR_LEN + 2;
402                 } else {
403                         *(u_int16_t *)&aad[30] = 0;
404                         b0[1] = 0;
405                         aad[1] = 22 + IEEE80211_ADDR_LEN;
406                 }
407         } else {
408                 if (IS_QOS_DATA(wh)) {
409                         struct ieee80211_qosframe *qwh =
410                                 (struct ieee80211_qosframe*) wh;
411                         aad[24] = qwh->i_qos[0] & 0x0f; /* just priority bits */
412                         aad[25] = 0;
413                         b0[1] = aad[24];
414                         aad[1] = 22 + 2;
415                 } else {
416                         *(u_int16_t *)&aad[24] = 0;
417                         b0[1] = 0;
418                         aad[1] = 22;
419                 }
420                 *(u_int16_t *)&aad[26] = 0;
421                 *(u_int32_t *)&aad[28] = 0;
422         }
423
424         /* Start with the first block and AAD */
425         rijndael_encrypt(tfm, b0, auth);
426         xor_block(auth, aad, AES_BLOCK_LEN);
427         rijndael_encrypt(tfm, auth, auth);
428         xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN);
429         rijndael_encrypt(tfm, auth, auth);
430         b0[0] &= 0x07;
431         b0[14] = b0[15] = 0;
432         rijndael_encrypt(tfm, b0, s0);
433 #undef  IS_QOS_DATA
434 #undef  IS_4ADDRESS
435 }
436
437 #define CCMP_ENCRYPT(_i, _b, _b0, _pos, _e, _len) do {  \
438         /* Authentication */                            \
439         xor_block(_b, _pos, _len);                      \
440         rijndael_encrypt(ctx->cc_tfm, _b, _b);          \
441         /* Encryption, with counter */                  \
442         _b0[14] = (_i >> 8) & 0xff;                     \
443         _b0[15] = _i & 0xff;                            \
444         rijndael_encrypt(ctx->cc_tfm, _b0, _e);         \
445         xor_block(_pos, _e, _len);                      \
446 } while (0)
447
448 static int
449 ccmp_encrypt(struct ieee80211_key *key, struct sk_buff *skb0, int hdrlen)
450 {
451         struct ccmp_ctx *ctx = key->wk_private;
452         struct ieee80211_frame *wh = (struct ieee80211_frame *) skb0->data;
453         struct sk_buff *skb;
454         int data_len, i;
455         uint8_t aad[2 * AES_BLOCK_LEN], b0[AES_BLOCK_LEN], b[AES_BLOCK_LEN];
456         uint8_t e[AES_BLOCK_LEN], s0[AES_BLOCK_LEN];
457         uint8_t *mic, *pos;
458         u_int space;
459
460         ctx->cc_vap->iv_stats.is_crypto_ccmp++;
461
462         skb = skb0;
463         data_len = skb->len;
464         while (skb->next != NULL) {
465                 skb = skb->next;
466                 data_len += skb->len;
467         }
468         data_len -= hdrlen + ccmp.ic_header;
469         if (skb_tailroom(skb) < ccmp.ic_trailer) {
470                 /* NB: should not happen */
471                 IEEE80211_NOTE_MAC(ctx->cc_vap, IEEE80211_MSG_CRYPTO,
472                         wh->i_addr1, "No room for %s MIC, tailroom %u",
473                         ccmp.ic_name, skb_tailroom(skb));
474                 /* XXX statistic */
475                 return 0;
476         }
477         ccmp_init_blocks(ctx->cc_tfm, wh, key->wk_keytsc,
478                 data_len, b0, aad, b, s0);
479
480         i = 1;
481         skb = skb0;
482         pos = skb->data + hdrlen + ccmp.ic_header;
483         /* NB: assumes header is entirely in first skbuf */
484         space = skb->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                 if (skb->next == NULL) {        /* last buffer */
500                         if (space != 0) {
501                                 /*
502                                  * Short last block.
503                                  */
504                                 CCMP_ENCRYPT(i, b, b0, pos, e, space);
505                         }
506                         break;
507                 }
508                 skb = skb->next;
509                 if (space != 0) {
510                         uint8_t *pos_next;
511                         u_int space_next;
512                         u_int len;
513
514                         /*
515                          * Block straddles buffers, split references.  We
516                          * do not handle splits that require >2 buffers.
517                          */
518                         pos_next = skb->data;
519                         len = min(data_len, AES_BLOCK_LEN);
520                         space_next = len > space ? len - space : 0;
521                         KASSERT(skb->len >= space_next,
522                                 ("not enough data in following buffer, "
523                                 "skb len %u need %u\n", skb->len, space_next));
524
525                         xor_block(b + space, pos_next, space_next);
526                         CCMP_ENCRYPT(i, b, b0, pos, e, space);
527                         xor_block(pos_next, e + space, space_next);
528                         data_len -= len;
529                         /* XXX could check for data_len <= 0 */
530                         i++;
531
532                         pos = pos_next + space_next;
533                         space = skb->len - space_next;
534                 } else {
535                         /*
536                          * Setup for next buffer.
537                          */
538                         pos = skb->data;
539                         space = skb->len;
540                 }
541         }
542         /* tack on MIC */
543         mic = skb_put(skb, ccmp.ic_trailer);
544         for (i = 0; i < ccmp.ic_trailer; i++)
545                 mic[i] = b[i] ^ s0[i];
546         return 1;
547 }
548 #undef CCMP_ENCRYPT
549
550 #define CCMP_DECRYPT(_i, _b, _b0, _pos, _a, _len) do {  \
551         /* Decrypt, with counter */                     \
552         _b0[14] = (_i >> 8) & 0xff;                     \
553         _b0[15] = _i & 0xff;                            \
554         rijndael_encrypt(ctx->cc_tfm, _b0, _b);         \
555         xor_block(_pos, _b, _len);                      \
556         /* Authentication */                            \
557         xor_block(_a, _pos, _len);                      \
558         rijndael_encrypt(ctx->cc_tfm, _a, _a);          \
559 } while (0)
560
561 static int
562 ccmp_decrypt(struct ieee80211_key *key, u_int64_t pn, struct sk_buff *skb0, int hdrlen)
563 {
564         struct ccmp_ctx *ctx = key->wk_private;
565         struct ieee80211_frame *wh = (struct ieee80211_frame *) skb0->data;
566         struct sk_buff *skb;
567         uint8_t aad[2 * AES_BLOCK_LEN];
568         uint8_t b0[AES_BLOCK_LEN], b[AES_BLOCK_LEN], a[AES_BLOCK_LEN];
569         size_t data_len;
570         int i;
571         uint8_t *pos, *mic;
572         u_int space;
573
574         ctx->cc_vap->iv_stats.is_crypto_ccmp++;
575
576         skb = skb0;
577         data_len = skb->len;
578         while (skb->next != NULL) {
579                 skb = skb->next;
580                 data_len += skb->len;
581         }
582         data_len -= hdrlen + ccmp.ic_header + ccmp.ic_trailer;
583         /* NB: skb left pointing at last in chain */
584         ccmp_init_blocks(ctx->cc_tfm, wh, pn, data_len, b0, aad, a, b);
585         /* NB: this is the last in the chain */
586         /* XXX assert skb->len >= ccmp.ic_trailer */
587         mic = skb->data + skb->len - ccmp.ic_trailer;
588         xor_block(mic, b, ccmp.ic_trailer);
589
590         i = 1;
591         skb = skb0;
592         pos = skb->data + hdrlen + ccmp.ic_header;
593         space = skb->len - (hdrlen + ccmp.ic_header);
594         for (;;) {
595                 if (space > data_len)
596                         space = data_len;
597                 while (space >= AES_BLOCK_LEN) {
598                         CCMP_DECRYPT(i, b, b0, pos, a, AES_BLOCK_LEN);
599                         pos += AES_BLOCK_LEN;
600                         space -= AES_BLOCK_LEN;
601                         data_len -= AES_BLOCK_LEN;
602                         i++;
603                 }
604                 if (data_len <= 0)              /* no more data */
605                         break;
606                 skb = skb->next;
607                 if (skb == NULL) {              /* last buffer */
608                         if (space != 0)         /* short last block */
609                                 CCMP_DECRYPT(i, b, b0, pos, a, space);
610                         break;
611                 }
612                 if (space != 0) {
613                         uint8_t *pos_next;
614                         u_int space_next;
615                         u_int len;
616
617                         /*
618                          * Block straddles buffers, split references.  We
619                          * do not handle splits that require >2 buffers.
620                          */
621                         pos_next = skb->data;
622                         len = min(data_len, (size_t) AES_BLOCK_LEN);
623                         space_next = len > space ? len - space : 0;
624                         KASSERT(skb->len >= space_next,
625                                 ("not enough data in following buffer, "
626                                 "skb len %u need %u\n", skb->len, space_next));
627
628                         xor_block(b+space, pos_next, space_next);
629                         CCMP_DECRYPT(i, b, b0, pos, a, space);
630                         xor_block(pos_next, b+space, space_next);
631                         data_len -= len;
632                         i++;
633
634                         pos = pos_next + space_next;
635                         space = skb->len - space_next;
636                 } else {
637                         /*
638                          * Setup for next buffer.
639                          */
640                         pos = skb->data;
641                         space = skb->len;
642                 }
643         }
644
645         if (memcmp(mic, a, ccmp.ic_trailer) != 0) {
646                 IEEE80211_NOTE_MAC(ctx->cc_vap, IEEE80211_MSG_CRYPTO,
647                         wh->i_addr2,
648                         "AES-CCM decrypt failed; MIC mismatch (keyix %u, rsc %llu)",
649                         key->wk_keyix, pn);
650                 ctx->cc_vap->iv_stats.is_rx_ccmpmic++;
651                 return 0;
652         }
653         return 1;
654 }
655 #undef CCMP_DECRYPT
656
657 /*
658  * Module glue.
659  */
660
661 MODULE_AUTHOR("Errno Consulting, Sam Leffler");
662 MODULE_DESCRIPTION("802.11 wireless support: AES-CCM cipher");
663 #ifdef MODULE_LICENSE
664 MODULE_LICENSE("Dual BSD/GPL");
665 #endif
666
667 static int __init
668 init_crypto_ccmp(void)
669 {
670         ieee80211_crypto_register(&ccmp);
671         return 0;
672 }
673 module_init(init_crypto_ccmp);
674
675 static void __exit
676 exit_crypto_ccmp(void)
677 {
678         ieee80211_crypto_unregister(&ccmp);
679 }
680 module_exit(exit_crypto_ccmp);