2 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
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.
31 * $Id: ieee80211_crypto_ccmp.c 3734 2008-06-19 16:58:07Z proski $
35 * IEEE 802.11i AES-CCMP crypto support.
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 * its license is included below.
41 #ifndef AUTOCONF_INCLUDED
42 #include <linux/config.h>
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>
51 #include <linux/crypto.h>
52 #include <asm/scatterlist.h>
56 #include <net80211/ieee80211_var.h>
58 #define AES_BLOCK_LEN 16
60 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
61 #define crypto_cipher crypto_tfm
65 struct ieee80211vap
*cc_vap
; /* for diagnostics + statistics */
66 struct ieee80211com
*cc_ic
;
67 struct crypto_cipher
*cc_tfm
;
70 static void *ccmp_attach(struct ieee80211vap
*, struct ieee80211_key
*);
71 static void ccmp_detach(struct ieee80211_key
*);
72 static int ccmp_setkey(struct ieee80211_key
*);
73 static int ccmp_encap(struct ieee80211_key
*, struct sk_buff
*, u_int8_t
);
74 static int ccmp_decap(struct ieee80211_key
*, struct sk_buff
*, int);
75 static int ccmp_enmic(struct ieee80211_key
*, struct sk_buff
*, int);
76 static int ccmp_demic(struct ieee80211_key
*, struct sk_buff
*, int, int);
78 static const struct ieee80211_cipher ccmp
= {
80 .ic_cipher
= IEEE80211_CIPHER_AES_CCM
,
81 .ic_header
= IEEE80211_WEP_IVLEN
+ IEEE80211_WEP_KIDLEN
+
82 IEEE80211_WEP_EXTIVLEN
,
83 .ic_trailer
= IEEE80211_WEP_MICLEN
,
85 .ic_attach
= ccmp_attach
,
86 .ic_detach
= ccmp_detach
,
87 .ic_setkey
= ccmp_setkey
,
88 .ic_encap
= ccmp_encap
,
89 .ic_decap
= ccmp_decap
,
90 .ic_enmic
= ccmp_enmic
,
91 .ic_demic
= ccmp_demic
,
94 static int ccmp_encrypt(struct ieee80211_key
*, struct sk_buff
*, int);
95 static int ccmp_decrypt(struct ieee80211_key
*, u_int64_t
, struct sk_buff
*, int);
98 ccmp_attach(struct ieee80211vap
*vap
, struct ieee80211_key
*k
)
100 struct ccmp_ctx
*ctx
;
103 _MOD_INC_USE(THIS_MODULE
, return NULL
);
105 MALLOC(ctx
, struct ccmp_ctx
*, sizeof(struct ccmp_ctx
),
106 M_DEVBUF
, M_NOWAIT
| M_ZERO
);
108 vap
->iv_stats
.is_crypto_nomem
++;
112 /* This function crypto_alloc_foo might sleep. Therefore:
113 * Context: process */
114 if (k
->wk_flags
& IEEE80211_KEY_SWCRYPT
) {
115 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
116 ctx
->cc_tfm
= crypto_alloc_tfm("aes", 0);
118 ctx
->cc_tfm
= crypto_alloc_cipher("aes", 0,
120 if (IS_ERR(ctx
->cc_tfm
))
124 if (ctx
->cc_tfm
== NULL
) {
125 IEEE80211_DPRINTF(vap
, IEEE80211_MSG_CRYPTO
,
126 "%s: kernel support for AES "
127 "cryptography is not available; the "
128 "module may not be loaded.\n",
132 vap
->iv_stats
.is_crypto_nocipher
++;
138 _MOD_DEC_USE(THIS_MODULE
);
141 ctx
->cc_ic
= vap
->iv_ic
;
148 ccmp_detach(struct ieee80211_key
*k
)
150 struct ccmp_ctx
*ctx
= k
->wk_private
;
152 if (ctx
->cc_tfm
!= NULL
)
153 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
154 crypto_free_tfm(ctx
->cc_tfm
);
156 crypto_free_cipher(ctx
->cc_tfm
);
160 _MOD_DEC_USE(THIS_MODULE
);
164 ccmp_setkey(struct ieee80211_key
*k
)
166 struct ccmp_ctx
*ctx
= k
->wk_private
;
168 if (k
->wk_keylen
!= (128 / NBBY
)) {
169 IEEE80211_DPRINTF(ctx
->cc_vap
, IEEE80211_MSG_CRYPTO
,
170 "%s: Invalid key length %u, expecting %u\n",
171 __func__
, k
->wk_keylen
, 128 / NBBY
);
175 if (k
->wk_flags
& IEEE80211_KEY_SWCRYPT
)
176 crypto_cipher_setkey(ctx
->cc_tfm
, k
->wk_key
, k
->wk_keylen
);
182 * Add privacy headers appropriate for the specified key.
185 ccmp_encap(struct ieee80211_key
*k
, struct sk_buff
*skb
, u_int8_t keyid
)
187 struct ccmp_ctx
*ctx
= k
->wk_private
;
188 struct ieee80211com
*ic
= ctx
->cc_ic
;
192 hdrlen
= ieee80211_hdrspace(ic
, skb
->data
);
195 * Copy down 802.11 header and add the IV, KeyID, and ExtIV.
197 ivp
= skb_push(skb
, ccmp
.ic_header
);
198 memmove(ivp
, ivp
+ ccmp
.ic_header
, hdrlen
);
201 k
->wk_keytsc
++; /* XXX wrap at 48 bits */
202 ivp
[0] = k
->wk_keytsc
>> 0; /* PN0 */
203 ivp
[1] = k
->wk_keytsc
>> 8; /* PN1 */
204 ivp
[2] = 0; /* Reserved */
205 ivp
[3] = keyid
| IEEE80211_WEP_EXTIV
; /* KeyID | ExtID */
206 ivp
[4] = k
->wk_keytsc
>> 16; /* PN2 */
207 ivp
[5] = k
->wk_keytsc
>> 24; /* PN3 */
208 ivp
[6] = k
->wk_keytsc
>> 32; /* PN4 */
209 ivp
[7] = k
->wk_keytsc
>> 40; /* PN5 */
212 * Finally, do software encrypt if neeed.
214 if ((k
->wk_flags
& IEEE80211_KEY_SWCRYPT
) &&
215 !ccmp_encrypt(k
, skb
, hdrlen
))
222 * Add MIC to the frame as needed.
225 ccmp_enmic(struct ieee80211_key
*k
, struct sk_buff
*skb
, int force_sw
)
230 static __inline
uint64_t
231 READ_6(uint8_t b0
, uint8_t b1
, uint8_t b2
, uint8_t b3
, uint8_t b4
, uint8_t b5
)
233 uint32_t iv32
= (b0
<< 0) | (b1
<< 8) | (b2
<< 16) | (b3
<< 24);
234 uint16_t iv16
= (b4
<< 0) | (b5
<< 8);
235 return (((uint64_t)iv16
) << 32) | iv32
;
239 * Validate and strip privacy headers (and trailer) for a
240 * received frame. The specified key should be correct but
244 ccmp_decap(struct ieee80211_key
*k
, struct sk_buff
*skb
, int hdrlen
)
246 struct ccmp_ctx
*ctx
= k
->wk_private
;
247 struct ieee80211vap
*vap
= ctx
->cc_vap
;
248 struct ieee80211_frame
*wh
;
254 * Header should have extended IV and sequence number;
255 * verify the former and validate the latter.
257 wh
= (struct ieee80211_frame
*)skb
->data
;
258 ivp
= skb
->data
+ hdrlen
;
259 if ((ivp
[IEEE80211_WEP_IVLEN
] & IEEE80211_WEP_EXTIV
) == 0) {
261 * No extended IV; discard frame.
263 IEEE80211_NOTE_MAC(vap
, IEEE80211_MSG_CRYPTO
, wh
->i_addr2
,
264 "%s", "Missing ExtIV for AES-CCM cipher");
265 vap
->iv_stats
.is_rx_ccmpformat
++;
269 if (IEEE80211_QOS_HAS_SEQ(wh
))
270 tid
= ((struct ieee80211_qosframe
*)wh
)->i_qos
[0] & IEEE80211_QOS_TID
;
271 /* NB: assume IEEE80211_WEP_MINLEN covers the extended IV */
272 pn
= READ_6(ivp
[0], ivp
[1], ivp
[4], ivp
[5], ivp
[6], ivp
[7]);
273 if (pn
&& pn
<= k
->wk_keyrsc
[tid
]) {
277 ieee80211_notify_replay_failure(vap
, wh
, k
, pn
);
278 vap
->iv_stats
.is_rx_ccmpreplay
++;
283 * Check if the device handled the decrypt in hardware.
284 * If so we just strip the header; otherwise we need to
285 * handle the decrypt in software. Note that for the
286 * latter we leave the header in place for use in the
289 if ((k
->wk_flags
& IEEE80211_KEY_SWCRYPT
) &&
290 !ccmp_decrypt(k
, pn
, skb
, hdrlen
))
294 * Copy up 802.11 header and strip crypto bits.
296 memmove(skb
->data
+ ccmp
.ic_header
, skb
->data
, hdrlen
);
297 skb_pull(skb
, ccmp
.ic_header
);
298 while (skb
->next
!= NULL
)
300 skb_trim(skb
, skb
->len
- ccmp
.ic_trailer
);
303 * Ok to update rsc now.
305 k
->wk_keyrsc
[tid
] = pn
;
311 * Verify and strip MIC from the frame.
314 ccmp_demic(struct ieee80211_key
*k
, struct sk_buff
*skb
, int hdrlen
, int force_sw
)
320 xor_block(u8
*b
, const u8
*a
, size_t len
)
323 for (i
= 0; i
< len
; i
++)
328 rijndael_encrypt(struct crypto_cipher
*tfm
, const void *src
, void *dst
)
330 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
331 crypto_cipher_encrypt_one(tfm
, dst
, src
);
333 struct scatterlist sg_src
;
334 struct scatterlist sg_dst
;
336 sg_src
.page
= virt_to_page(src
);
337 sg_src
.offset
= offset_in_page(src
);
338 sg_src
.length
= AES_BLOCK_LEN
;
340 sg_dst
.page
= virt_to_page(dst
);
341 sg_dst
.offset
= offset_in_page(dst
);
342 sg_dst
.length
= AES_BLOCK_LEN
;
343 crypto_cipher_encrypt(tfm
, &sg_dst
, &sg_src
, AES_BLOCK_LEN
);
348 * Host AP crypt: host-based CCMP encryption implementation for Host AP driver
350 * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
352 * This program is free software; you can redistribute it and/or modify
353 * it under the terms of the GNU General Public License version 2 as
354 * published by the Free Software Foundation. See README and COPYING for
357 * Alternatively, this software may be distributed under the terms of BSD
362 ccmp_init_blocks(struct crypto_cipher
*tfm
, struct ieee80211_frame
*wh
,
363 u_int64_t pn
, size_t dlen
,
364 uint8_t b0
[AES_BLOCK_LEN
], uint8_t aad
[2 * AES_BLOCK_LEN
],
365 uint8_t auth
[AES_BLOCK_LEN
], uint8_t s0
[AES_BLOCK_LEN
])
367 #define IS_4ADDRESS(wh) \
368 ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
369 #define IS_QOS_DATA(wh) IEEE80211_QOS_HAS_SEQ(wh)
371 /* CCM Initial Block:
372 * Flag (Include authentication header, M=3 (8-octet MIC),
373 * L=1 (2-octet Dlen))
374 * Nonce: 0x00 | A2 | PN
377 /* NB: b0[1] set below */
378 IEEE80211_ADDR_COPY(b0
+ 2, wh
->i_addr2
);
385 b0
[14] = (dlen
>> 8) & 0xff;
386 b0
[15] = dlen
& 0xff;
389 * FC with bits 4..6 and 11..13 masked to zero; 14 is always one
391 * SC with bits 4..15 (seq#) masked to zero
395 aad
[0] = 0; /* AAD length >> 8 */
396 /* NB: aad[1] set below */
397 aad
[2] = wh
->i_fc
[0] & 0x8f; /* XXX magic #s */
398 aad
[3] = wh
->i_fc
[1] & 0xc7; /* XXX magic #s */
399 /* NB: we know 3 addresses are contiguous */
400 memcpy(aad
+ 4, wh
->i_addr1
, 3 * IEEE80211_ADDR_LEN
);
401 aad
[22] = wh
->i_seq
[0] & IEEE80211_SEQ_FRAG_MASK
;
402 aad
[23] = 0; /* all bits masked */
404 * Construct variable-length portion of AAD based
405 * on whether this is a 4-address frame/QOS frame.
406 * We always zero-pad to 32 bytes before running it
407 * through the cipher.
409 * We also fill in the priority bits of the CCM
410 * initial block as we know whether or not we have
413 if (IS_4ADDRESS(wh
)) {
414 IEEE80211_ADDR_COPY(aad
+ 24,
415 ((struct ieee80211_frame_addr4
*)wh
)->i_addr4
);
416 if (IS_QOS_DATA(wh
)) {
417 struct ieee80211_qosframe_addr4
*qwh4
=
418 (struct ieee80211_qosframe_addr4
*)wh
;
419 aad
[30] = qwh4
->i_qos
[0] & 0x0f;/* just priority bits */
422 aad
[1] = 22 + IEEE80211_ADDR_LEN
+ 2;
424 *(u_int16_t
*)&aad
[30] = 0;
426 aad
[1] = 22 + IEEE80211_ADDR_LEN
;
429 if (IS_QOS_DATA(wh
)) {
430 struct ieee80211_qosframe
*qwh
=
431 (struct ieee80211_qosframe
*)wh
;
432 aad
[24] = qwh
->i_qos
[0] & 0x0f; /* just priority bits */
437 *(u_int16_t
*)&aad
[24] = 0;
441 *(u_int16_t
*)&aad
[26] = 0;
442 *(u_int32_t
*)&aad
[28] = 0;
445 /* Start with the first block and AAD */
446 rijndael_encrypt(tfm
, b0
, auth
);
447 xor_block(auth
, aad
, AES_BLOCK_LEN
);
448 rijndael_encrypt(tfm
, auth
, auth
);
449 xor_block(auth
, &aad
[AES_BLOCK_LEN
], AES_BLOCK_LEN
);
450 rijndael_encrypt(tfm
, auth
, auth
);
453 rijndael_encrypt(tfm
, b0
, s0
);
458 #define CCMP_ENCRYPT(_i, _b, _b0, _pos, _e, _len) do { \
459 /* Authentication */ \
460 xor_block(_b, _pos, _len); \
461 rijndael_encrypt(ctx->cc_tfm, _b, _b); \
462 /* Encryption, with counter */ \
463 _b0[14] = (_i >> 8) & 0xff; \
464 _b0[15] = _i & 0xff; \
465 rijndael_encrypt(ctx->cc_tfm, _b0, _e); \
466 xor_block(_pos, _e, _len); \
470 ccmp_encrypt(struct ieee80211_key
*key
, struct sk_buff
*skb0
, int hdrlen
)
472 struct ccmp_ctx
*ctx
= key
->wk_private
;
473 struct ieee80211_frame
*wh
= (struct ieee80211_frame
*)skb0
->data
;
476 uint8_t aad
[2 * AES_BLOCK_LEN
], b0
[AES_BLOCK_LEN
], b
[AES_BLOCK_LEN
];
477 uint8_t e
[AES_BLOCK_LEN
], s0
[AES_BLOCK_LEN
];
481 ctx
->cc_vap
->iv_stats
.is_crypto_ccmp
++;
485 while (skb
->next
!= NULL
) {
487 data_len
+= skb
->len
;
489 data_len
-= hdrlen
+ ccmp
.ic_header
;
490 if (skb_tailroom(skb
) < ccmp
.ic_trailer
) {
491 /* NB: should not happen */
492 IEEE80211_NOTE_MAC(ctx
->cc_vap
, IEEE80211_MSG_CRYPTO
,
493 wh
->i_addr1
, "No room for %s MIC, tailroom %u",
494 ccmp
.ic_name
, skb_tailroom(skb
));
498 ccmp_init_blocks(ctx
->cc_tfm
, wh
, key
->wk_keytsc
,
499 data_len
, b0
, aad
, b
, s0
);
503 pos
= skb
->data
+ hdrlen
+ ccmp
.ic_header
;
504 /* NB: assumes header is entirely in first skbuf */
505 space
= skb
->len
- (hdrlen
+ ccmp
.ic_header
);
507 if (space
> data_len
)
512 while (space
>= AES_BLOCK_LEN
) {
513 CCMP_ENCRYPT(i
, b
, b0
, pos
, e
, AES_BLOCK_LEN
);
514 pos
+= AES_BLOCK_LEN
, space
-= AES_BLOCK_LEN
;
515 data_len
-= AES_BLOCK_LEN
;
518 if (data_len
<= 0) /* no more data */
520 if (skb
->next
== NULL
) { /* last buffer */
525 CCMP_ENCRYPT(i
, b
, b0
, pos
, e
, space
);
536 * Block straddles buffers, split references. We
537 * do not handle splits that require >2 buffers.
539 pos_next
= skb
->data
;
540 len
= min(data_len
, AES_BLOCK_LEN
);
541 space_next
= len
> space
? len
- space
: 0;
542 KASSERT(skb
->len
>= space_next
,
543 ("not enough data in following buffer, "
544 "skb len %u need %u", skb
->len
, space_next
));
546 xor_block(b
+ space
, pos_next
, space_next
);
547 CCMP_ENCRYPT(i
, b
, b0
, pos
, e
, space
);
548 xor_block(pos_next
, e
+ space
, space_next
);
550 /* XXX could check for data_len <= 0 */
553 pos
= pos_next
+ space_next
;
554 space
= skb
->len
- space_next
;
557 * Setup for next buffer.
564 mic
= skb_put(skb
, ccmp
.ic_trailer
);
565 for (i
= 0; i
< ccmp
.ic_trailer
; i
++)
566 mic
[i
] = b
[i
] ^ s0
[i
];
571 #define CCMP_DECRYPT(_i, _b, _b0, _pos, _a, _len) do { \
572 /* Decrypt, with counter */ \
573 _b0[14] = (_i >> 8) & 0xff; \
574 _b0[15] = _i & 0xff; \
575 rijndael_encrypt(ctx->cc_tfm, _b0, _b); \
576 xor_block(_pos, _b, _len); \
577 /* Authentication */ \
578 xor_block(_a, _pos, _len); \
579 rijndael_encrypt(ctx->cc_tfm, _a, _a); \
583 ccmp_decrypt(struct ieee80211_key
*key
, u_int64_t pn
, struct sk_buff
*skb0
, int hdrlen
)
585 struct ccmp_ctx
*ctx
= key
->wk_private
;
586 struct ieee80211_frame
*wh
= (struct ieee80211_frame
*)skb0
->data
;
588 uint8_t aad
[2 * AES_BLOCK_LEN
];
589 uint8_t b0
[AES_BLOCK_LEN
], b
[AES_BLOCK_LEN
], a
[AES_BLOCK_LEN
];
595 ctx
->cc_vap
->iv_stats
.is_crypto_ccmp
++;
599 while (skb
->next
!= NULL
) {
601 data_len
+= skb
->len
;
603 data_len
-= hdrlen
+ ccmp
.ic_header
+ ccmp
.ic_trailer
;
604 /* NB: skb left pointing at last in chain */
605 ccmp_init_blocks(ctx
->cc_tfm
, wh
, pn
, data_len
, b0
, aad
, a
, b
);
606 /* NB: this is the last in the chain */
607 /* XXX assert skb->len >= ccmp.ic_trailer */
608 mic
= skb
->data
+ skb
->len
- ccmp
.ic_trailer
;
609 xor_block(mic
, b
, ccmp
.ic_trailer
);
613 pos
= skb
->data
+ hdrlen
+ ccmp
.ic_header
;
614 space
= skb
->len
- (hdrlen
+ ccmp
.ic_header
);
616 if (space
> data_len
)
618 while (space
>= AES_BLOCK_LEN
) {
619 CCMP_DECRYPT(i
, b
, b0
, pos
, a
, AES_BLOCK_LEN
);
620 pos
+= AES_BLOCK_LEN
;
621 space
-= AES_BLOCK_LEN
;
622 data_len
-= AES_BLOCK_LEN
;
625 if (data_len
<= 0) /* no more data */
628 if (skb
== NULL
) { /* last buffer */
629 if (space
!= 0) /* short last block */
630 CCMP_DECRYPT(i
, b
, b0
, pos
, a
, space
);
639 * Block straddles buffers, split references. We
640 * do not handle splits that require >2 buffers.
642 pos_next
= skb
->data
;
643 len
= min(data_len
, (size_t) AES_BLOCK_LEN
);
644 space_next
= len
> space
? len
- space
: 0;
645 KASSERT(skb
->len
>= space_next
,
646 ("not enough data in following buffer, "
647 "skb len %u need %u", skb
->len
, space_next
));
649 xor_block(b
+space
, pos_next
, space_next
);
650 CCMP_DECRYPT(i
, b
, b0
, pos
, a
, space
);
651 xor_block(pos_next
, b
+space
, space_next
);
655 pos
= pos_next
+ space_next
;
656 space
= skb
->len
- space_next
;
659 * Setup for next buffer.
666 if (memcmp(mic
, a
, ccmp
.ic_trailer
) != 0) {
667 IEEE80211_NOTE_MAC(ctx
->cc_vap
, IEEE80211_MSG_CRYPTO
,
669 "AES-CCM decrypt failed; MIC mismatch (keyix %u, rsc %llu)",
670 key
->wk_keyix
, (unsigned long long)pn
);
671 ctx
->cc_vap
->iv_stats
.is_rx_ccmpmic
++;
682 MODULE_AUTHOR("Errno Consulting, Sam Leffler");
683 MODULE_DESCRIPTION("802.11 wireless support: AES-CCM cipher");
684 #ifdef MODULE_LICENSE
685 MODULE_LICENSE("Dual BSD/GPL");
689 init_crypto_ccmp(void)
691 ieee80211_crypto_register(&ccmp
);
694 module_init(init_crypto_ccmp
);
697 exit_crypto_ccmp(void)
699 ieee80211_crypto_unregister(&ccmp
);
701 module_exit(exit_crypto_ccmp
);