2 * Host AP crypt: host-based TKIP encryption implementation for Host AP driver
4 * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation. See README and COPYING for
12 #include <linux/config.h>
13 #include <linux/version.h>
14 #include <linux/module.h>
15 #include <linux/init.h>
16 #include <linux/slab.h>
17 #include <linux/random.h>
18 #include <linux/skbuff.h>
19 #include <linux/netdevice.h>
20 #include <linux/if_ether.h>
21 #include <linux/if_arp.h>
22 #include <linux/wireless.h>
23 #include <net/iw_handler.h>
24 #include <asm/string.h>
26 #include "hostap_crypt.h"
27 #include "hostap_wlan.h"
28 #include "hostap_80211.h"
29 #include "hostap_config.h"
32 #error CONFIG_CRYPTO is required to build this module.
34 #include <linux/crypto.h>
35 #include <asm/scatterlist.h>
36 #include <linux/crc32.h>
38 MODULE_AUTHOR("Jouni Malinen");
39 MODULE_DESCRIPTION("Host AP crypt: TKIP");
40 MODULE_LICENSE("GPL");
41 MODULE_VERSION(PRISM2_VERSION);
44 struct hostap_tkip_data {
45 #define TKIP_KEY_LEN 32
61 u32 dot11RSNAStatsTKIPReplays;
62 u32 dot11RSNAStatsTKIPICVErrors;
63 u32 dot11RSNAStatsTKIPLocalMICFailures;
67 struct crypto_tfm *tfm_arc4;
68 struct crypto_tfm *tfm_michael;
70 /* scratch buffers for virt_to_page() (crypto API) */
71 u8 rx_hdr[16], tx_hdr[16];
75 static void * hostap_tkip_init(int key_idx)
77 struct hostap_tkip_data *priv;
79 if (!try_module_get(THIS_MODULE))
82 priv = (struct hostap_tkip_data *) kmalloc(sizeof(*priv), GFP_ATOMIC);
85 memset(priv, 0, sizeof(*priv));
86 priv->key_idx = key_idx;
88 priv->tfm_arc4 = crypto_alloc_tfm("arc4", 0);
89 if (priv->tfm_arc4 == NULL) {
90 printk(KERN_DEBUG "hostap_crypt_tkip: could not allocate "
95 priv->tfm_michael = crypto_alloc_tfm("michael_mic", 0);
96 if (priv->tfm_michael == NULL) {
97 printk(KERN_DEBUG "hostap_crypt_tkip: could not allocate "
98 "crypto API michael_mic\n");
106 if (priv->tfm_michael)
107 crypto_free_tfm(priv->tfm_michael);
109 crypto_free_tfm(priv->tfm_arc4);
112 module_put(THIS_MODULE);
117 static void hostap_tkip_deinit(void *priv)
119 struct hostap_tkip_data *_priv = priv;
120 if (_priv && _priv->tfm_michael)
121 crypto_free_tfm(_priv->tfm_michael);
122 if (_priv && _priv->tfm_arc4)
123 crypto_free_tfm(_priv->tfm_arc4);
125 module_put(THIS_MODULE);
129 static inline u16 RotR1(u16 val)
131 return (val >> 1) | (val << 15);
135 static inline u8 Lo8(u16 val)
141 static inline u8 Hi8(u16 val)
147 static inline u16 Lo16(u32 val)
153 static inline u16 Hi16(u32 val)
159 static inline u16 Mk16(u8 hi, u8 lo)
161 return lo | (((u16) hi) << 8);
165 static inline u16 Mk16_le(u16 *v)
167 return le16_to_cpu(*v);
171 static const u16 Sbox[256] =
173 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
174 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
175 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
176 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
177 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
178 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
179 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
180 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
181 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
182 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
183 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
184 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
185 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
186 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
187 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
188 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
189 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
190 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
191 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
192 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
193 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
194 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
195 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
196 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
197 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
198 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
199 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
200 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
201 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
202 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
203 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
204 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
208 static inline u16 _S_(u16 v)
210 u16 t = Sbox[Hi8(v)];
211 return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8));
215 #define PHASE1_LOOP_COUNT 8
217 static void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32)
221 /* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */
222 TTAK[0] = Lo16(IV32);
223 TTAK[1] = Hi16(IV32);
224 TTAK[2] = Mk16(TA[1], TA[0]);
225 TTAK[3] = Mk16(TA[3], TA[2]);
226 TTAK[4] = Mk16(TA[5], TA[4]);
228 for (i = 0; i < PHASE1_LOOP_COUNT; i++) {
230 TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j]));
231 TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j]));
232 TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j]));
233 TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j]));
234 TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i;
239 static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK,
242 /* Make temporary area overlap WEP seed so that the final copy can be
243 * avoided on little endian hosts. */
244 u16 *PPK = (u16 *) &WEPSeed[4];
246 /* Step 1 - make copy of TTAK and bring in TSC */
252 PPK[5] = TTAK[4] + IV16;
254 /* Step 2 - 96-bit bijective mixing using S-box */
255 PPK[0] += _S_(PPK[5] ^ Mk16_le((u16 *) &TK[0]));
256 PPK[1] += _S_(PPK[0] ^ Mk16_le((u16 *) &TK[2]));
257 PPK[2] += _S_(PPK[1] ^ Mk16_le((u16 *) &TK[4]));
258 PPK[3] += _S_(PPK[2] ^ Mk16_le((u16 *) &TK[6]));
259 PPK[4] += _S_(PPK[3] ^ Mk16_le((u16 *) &TK[8]));
260 PPK[5] += _S_(PPK[4] ^ Mk16_le((u16 *) &TK[10]));
262 PPK[0] += RotR1(PPK[5] ^ Mk16_le((u16 *) &TK[12]));
263 PPK[1] += RotR1(PPK[0] ^ Mk16_le((u16 *) &TK[14]));
264 PPK[2] += RotR1(PPK[1]);
265 PPK[3] += RotR1(PPK[2]);
266 PPK[4] += RotR1(PPK[3]);
267 PPK[5] += RotR1(PPK[4]);
269 /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value
270 * WEPSeed[0..2] is transmitted as WEP IV */
271 WEPSeed[0] = Hi8(IV16);
272 WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F;
273 WEPSeed[2] = Lo8(IV16);
274 WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((u16 *) &TK[0])) >> 1);
279 for (i = 0; i < 6; i++)
280 PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8);
286 static int hostap_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
288 struct hostap_tkip_data *tkey = priv;
290 u8 rc4key[16], *pos, *icv;
291 struct hostap_ieee80211_hdr *hdr;
293 struct scatterlist sg;
295 if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 ||
299 hdr = (struct hostap_ieee80211_hdr *) skb->data;
300 if (!tkey->tx_phase1_done) {
301 tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
303 tkey->tx_phase1_done = 1;
305 tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);
307 len = skb->len - hdr_len;
308 pos = skb_push(skb, 8);
309 memmove(pos, pos + 8, hdr_len);
311 icv = skb_put(skb, 4);
316 *pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */;
317 *pos++ = tkey->tx_iv32 & 0xff;
318 *pos++ = (tkey->tx_iv32 >> 8) & 0xff;
319 *pos++ = (tkey->tx_iv32 >> 16) & 0xff;
320 *pos++ = (tkey->tx_iv32 >> 24) & 0xff;
322 crc = ~crc32_le(~0, pos, len);
328 crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
329 sg.page = virt_to_page(pos);
330 sg.offset = offset_in_page(pos);
332 crypto_cipher_encrypt(tkey->tfm_arc4, &sg, &sg, len + 4);
335 if (tkey->tx_iv16 == 0) {
336 tkey->tx_phase1_done = 0;
344 static int hostap_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
346 struct hostap_tkip_data *tkey = priv;
348 u8 keyidx, *pos, icv[4];
351 struct hostap_ieee80211_hdr *hdr;
353 struct scatterlist sg;
356 if (skb->len < hdr_len + 8 + 4)
359 hdr = (struct hostap_ieee80211_hdr *) skb->data;
360 pos = skb->data + hdr_len;
362 if (!(keyidx & (1 << 5))) {
363 if (net_ratelimit()) {
364 printk(KERN_DEBUG "TKIP: received packet without ExtIV"
365 " flag from " MACSTR "\n", MAC2STR(hdr->addr2));
370 if (tkey->key_idx != keyidx) {
371 printk(KERN_DEBUG "TKIP: RX tkey->key_idx=%d frame "
372 "keyidx=%d priv=%p\n", tkey->key_idx, keyidx, priv);
375 if (!tkey->key_set) {
376 if (net_ratelimit()) {
377 printk(KERN_DEBUG "TKIP: received packet from " MACSTR
378 " with keyid=%d that does not have a configured"
379 " key\n", MAC2STR(hdr->addr2), keyidx);
383 iv16 = (pos[0] << 8) | pos[2];
384 iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
387 if (iv32 < tkey->rx_iv32 ||
388 (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {
389 if (net_ratelimit()) {
390 printk(KERN_DEBUG "TKIP: replay detected: STA=" MACSTR
391 " previous TSC %08x%04x received TSC "
392 "%08x%04x\n", MAC2STR(hdr->addr2),
393 tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
395 tkey->dot11RSNAStatsTKIPReplays++;
399 if (iv32 != tkey->rx_iv32 || !tkey->rx_phase1_done) {
400 tkip_mixing_phase1(tkey->rx_ttak, tkey->key, hdr->addr2, iv32);
401 tkey->rx_phase1_done = 1;
403 tkip_mixing_phase2(rc4key, tkey->key, tkey->rx_ttak, iv16);
405 plen = skb->len - hdr_len - 12;
407 crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
408 sg.page = virt_to_page(pos);
409 sg.offset = offset_in_page(pos);
410 sg.length = plen + 4;
411 crypto_cipher_decrypt(tkey->tfm_arc4, &sg, &sg, plen + 4);
413 crc = ~crc32_le(~0, pos, plen);
418 if (memcmp(icv, pos + plen, 4) != 0) {
419 if (iv32 != tkey->rx_iv32) {
420 /* Previously cached Phase1 result was already lost, so
421 * it needs to be recalculated for the next packet. */
422 tkey->rx_phase1_done = 0;
424 if (net_ratelimit()) {
425 printk(KERN_DEBUG "TKIP: ICV error detected: STA="
426 MACSTR "\n", MAC2STR(hdr->addr2));
428 tkey->dot11RSNAStatsTKIPICVErrors++;
432 /* Update real counters only after Michael MIC verification has
434 tkey->rx_iv32_new = iv32;
435 tkey->rx_iv16_new = iv16;
437 /* Remove IV and ICV */
438 memmove(skb->data + 8, skb->data, hdr_len);
440 skb_trim(skb, skb->len - 4);
446 static int michael_mic(struct hostap_tkip_data *tkey, u8 *key, u8 *hdr,
447 u8 *data, size_t data_len, u8 *mic)
449 struct scatterlist sg[2];
451 if (tkey->tfm_michael == NULL) {
452 printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
455 sg[0].page = virt_to_page(hdr);
456 sg[0].offset = offset_in_page(hdr);
459 sg[1].page = virt_to_page(data);
460 sg[1].offset = offset_in_page(data);
461 sg[1].length = data_len;
463 crypto_digest_init(tkey->tfm_michael);
464 crypto_digest_setkey(tkey->tfm_michael, key, 8);
465 crypto_digest_update(tkey->tfm_michael, sg, 2);
466 crypto_digest_final(tkey->tfm_michael, mic);
472 static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr)
474 struct hostap_ieee80211_hdr *hdr11;
476 hdr11 = (struct hostap_ieee80211_hdr *) skb->data;
477 switch (le16_to_cpu(hdr11->frame_control) &
478 (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
480 memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
481 memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
484 memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
485 memcpy(hdr + ETH_ALEN, hdr11->addr3, ETH_ALEN); /* SA */
487 case WLAN_FC_FROMDS | WLAN_FC_TODS:
488 memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
489 memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */
492 memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
493 memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
497 hdr[12] = 0; /* priority */
498 hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */
502 static int hostap_michael_mic_add(struct sk_buff *skb, int hdr_len, void *priv)
504 struct hostap_tkip_data *tkey = priv;
507 if (skb_tailroom(skb) < 8 || skb->len < hdr_len) {
508 printk(KERN_DEBUG "Invalid packet for Michael MIC add "
509 "(tailroom=%d hdr_len=%d skb->len=%d)\n",
510 skb_tailroom(skb), hdr_len, skb->len);
514 michael_mic_hdr(skb, tkey->tx_hdr);
515 pos = skb_put(skb, 8);
516 if (michael_mic(tkey, &tkey->key[16], tkey->tx_hdr,
517 skb->data + hdr_len, skb->len - 8 - hdr_len, pos))
524 static void hostap_michael_mic_failure(struct net_device *dev,
525 struct hostap_ieee80211_hdr *hdr,
528 union iwreq_data wrqu;
531 /* TODO: needed parameters: count, keyid, key type, src address, TSC */
532 sprintf(buf, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr="
533 MACSTR ")", keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni",
534 MAC2STR(hdr->addr2));
535 memset(&wrqu, 0, sizeof(wrqu));
536 wrqu.data.length = strlen(buf);
537 wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
541 static int hostap_michael_mic_verify(struct sk_buff *skb, int keyidx,
542 int hdr_len, void *priv)
544 struct hostap_tkip_data *tkey = priv;
550 michael_mic_hdr(skb, tkey->rx_hdr);
551 if (michael_mic(tkey, &tkey->key[24], tkey->rx_hdr,
552 skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
554 if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
555 struct hostap_ieee80211_hdr *hdr;
556 hdr = (struct hostap_ieee80211_hdr *) skb->data;
557 printk(KERN_DEBUG "%s: Michael MIC verification failed for "
558 "MSDU from " MACSTR " keyidx=%d\n",
559 skb->dev ? skb->dev->name : "N/A", MAC2STR(hdr->addr2),
562 hostap_michael_mic_failure(skb->dev, hdr, keyidx);
563 tkey->dot11RSNAStatsTKIPLocalMICFailures++;
567 /* Update TSC counters for RX now that the packet verification has
569 tkey->rx_iv32 = tkey->rx_iv32_new;
570 tkey->rx_iv16 = tkey->rx_iv16_new;
572 skb_trim(skb, skb->len - 8);
578 static int hostap_tkip_set_key(void *key, int len, u8 *seq, void *priv)
580 struct hostap_tkip_data *tkey = priv;
582 struct crypto_tfm *tfm = tkey->tfm_michael;
583 struct crypto_tfm *tfm2 = tkey->tfm_arc4;
585 keyidx = tkey->key_idx;
586 memset(tkey, 0, sizeof(*tkey));
587 tkey->key_idx = keyidx;
588 tkey->tfm_michael = tfm;
589 tkey->tfm_arc4 = tfm2;
590 if (len == TKIP_KEY_LEN) {
591 memcpy(tkey->key, key, TKIP_KEY_LEN);
593 tkey->tx_iv16 = 1; /* TSC is initialized to 1 */
595 tkey->rx_iv32 = (seq[5] << 24) | (seq[4] << 16) |
596 (seq[3] << 8) | seq[2];
597 tkey->rx_iv16 = (seq[1] << 8) | seq[0];
599 } else if (len == 0) {
608 static int hostap_tkip_get_key(void *key, int len, u8 *seq, void *priv)
610 struct hostap_tkip_data *tkey = priv;
612 if (len < TKIP_KEY_LEN)
617 memcpy(key, tkey->key, TKIP_KEY_LEN);
620 /* Return the sequence number of the last transmitted frame. */
621 u16 iv16 = tkey->tx_iv16;
622 u32 iv32 = tkey->tx_iv32;
626 seq[0] = tkey->tx_iv16;
627 seq[1] = tkey->tx_iv16 >> 8;
628 seq[2] = tkey->tx_iv32;
629 seq[3] = tkey->tx_iv32 >> 8;
630 seq[4] = tkey->tx_iv32 >> 16;
631 seq[5] = tkey->tx_iv32 >> 24;
638 static char * hostap_tkip_print_stats(char *p, void *priv)
640 struct hostap_tkip_data *tkip = priv;
641 p += sprintf(p, "key[%d] alg=TKIP key_set=%d "
642 "tx_pn=%02x%02x%02x%02x%02x%02x "
643 "rx_pn=%02x%02x%02x%02x%02x%02x "
644 "replays=%d icv_errors=%d local_mic_failures=%d\n",
645 tkip->key_idx, tkip->key_set,
646 (tkip->tx_iv32 >> 24) & 0xff,
647 (tkip->tx_iv32 >> 16) & 0xff,
648 (tkip->tx_iv32 >> 8) & 0xff,
649 tkip->tx_iv32 & 0xff,
650 (tkip->tx_iv16 >> 8) & 0xff,
651 tkip->tx_iv16 & 0xff,
652 (tkip->rx_iv32 >> 24) & 0xff,
653 (tkip->rx_iv32 >> 16) & 0xff,
654 (tkip->rx_iv32 >> 8) & 0xff,
655 tkip->rx_iv32 & 0xff,
656 (tkip->rx_iv16 >> 8) & 0xff,
657 tkip->rx_iv16 & 0xff,
658 tkip->dot11RSNAStatsTKIPReplays,
659 tkip->dot11RSNAStatsTKIPICVErrors,
660 tkip->dot11RSNAStatsTKIPLocalMICFailures);
665 static struct hostap_crypto_ops hostap_crypt_tkip = {
667 .init = hostap_tkip_init,
668 .deinit = hostap_tkip_deinit,
669 .encrypt_mpdu = hostap_tkip_encrypt,
670 .decrypt_mpdu = hostap_tkip_decrypt,
671 .encrypt_msdu = hostap_michael_mic_add,
672 .decrypt_msdu = hostap_michael_mic_verify,
673 .set_key = hostap_tkip_set_key,
674 .get_key = hostap_tkip_get_key,
675 .print_stats = hostap_tkip_print_stats,
676 .extra_prefix_len = 4 + 4 /* IV + ExtIV */,
677 .extra_postfix_len = 8 + 4 /* MIC + ICV */
681 static int __init hostap_crypto_tkip_init(void)
683 if (hostap_register_crypto_ops(&hostap_crypt_tkip) < 0)
690 static void __exit hostap_crypto_tkip_exit(void)
692 hostap_unregister_crypto_ops(&hostap_crypt_tkip);
696 module_init(hostap_crypto_tkip_init);
697 module_exit(hostap_crypto_tkip_exit);