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");
43 struct hostap_tkip_data {
44 #define TKIP_KEY_LEN 32
60 u32 dot11RSNAStatsTKIPReplays;
61 u32 dot11RSNAStatsTKIPICVErrors;
62 u32 dot11RSNAStatsTKIPLocalMICFailures;
66 struct crypto_tfm *tfm_arc4;
67 struct crypto_tfm *tfm_michael;
69 /* scratch buffers for virt_to_page() (crypto API) */
70 u8 rx_hdr[16], tx_hdr[16];
74 static void * hostap_tkip_init(int key_idx)
76 struct hostap_tkip_data *priv;
78 if (!try_module_get(THIS_MODULE))
81 priv = (struct hostap_tkip_data *) kmalloc(sizeof(*priv), GFP_ATOMIC);
84 memset(priv, 0, sizeof(*priv));
85 priv->key_idx = key_idx;
87 priv->tfm_arc4 = crypto_alloc_tfm("arc4", 0);
88 if (priv->tfm_arc4 == NULL) {
89 printk(KERN_DEBUG "hostap_crypt_tkip: could not allocate "
94 priv->tfm_michael = crypto_alloc_tfm("michael_mic", 0);
95 if (priv->tfm_michael == NULL) {
96 printk(KERN_DEBUG "hostap_crypt_tkip: could not allocate "
97 "crypto API michael_mic\n");
105 if (priv->tfm_michael)
106 crypto_free_tfm(priv->tfm_michael);
108 crypto_free_tfm(priv->tfm_arc4);
111 module_put(THIS_MODULE);
116 static void hostap_tkip_deinit(void *priv)
118 struct hostap_tkip_data *_priv = priv;
119 if (_priv && _priv->tfm_michael)
120 crypto_free_tfm(_priv->tfm_michael);
121 if (_priv && _priv->tfm_arc4)
122 crypto_free_tfm(_priv->tfm_arc4);
124 module_put(THIS_MODULE);
128 static inline u16 RotR1(u16 val)
130 return (val >> 1) | (val << 15);
134 static inline u8 Lo8(u16 val)
140 static inline u8 Hi8(u16 val)
146 static inline u16 Lo16(u32 val)
152 static inline u16 Hi16(u32 val)
158 static inline u16 Mk16(u8 hi, u8 lo)
160 return lo | (((u16) hi) << 8);
164 static inline u16 Mk16_le(u16 *v)
166 return le16_to_cpu(*v);
170 static const u16 Sbox[256] =
172 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
173 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
174 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
175 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
176 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
177 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
178 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
179 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
180 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
181 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
182 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
183 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
184 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
185 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
186 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
187 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
188 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
189 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
190 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
191 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
192 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
193 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
194 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
195 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
196 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
197 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
198 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
199 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
200 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
201 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
202 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
203 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
207 static inline u16 _S_(u16 v)
209 u16 t = Sbox[Hi8(v)];
210 return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8));
214 #define PHASE1_LOOP_COUNT 8
216 static void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32)
220 /* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */
221 TTAK[0] = Lo16(IV32);
222 TTAK[1] = Hi16(IV32);
223 TTAK[2] = Mk16(TA[1], TA[0]);
224 TTAK[3] = Mk16(TA[3], TA[2]);
225 TTAK[4] = Mk16(TA[5], TA[4]);
227 for (i = 0; i < PHASE1_LOOP_COUNT; i++) {
229 TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j]));
230 TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j]));
231 TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j]));
232 TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j]));
233 TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i;
238 static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK,
241 /* Make temporary area overlap WEP seed so that the final copy can be
242 * avoided on little endian hosts. */
243 u16 *PPK = (u16 *) &WEPSeed[4];
245 /* Step 1 - make copy of TTAK and bring in TSC */
251 PPK[5] = TTAK[4] + IV16;
253 /* Step 2 - 96-bit bijective mixing using S-box */
254 PPK[0] += _S_(PPK[5] ^ Mk16_le((u16 *) &TK[0]));
255 PPK[1] += _S_(PPK[0] ^ Mk16_le((u16 *) &TK[2]));
256 PPK[2] += _S_(PPK[1] ^ Mk16_le((u16 *) &TK[4]));
257 PPK[3] += _S_(PPK[2] ^ Mk16_le((u16 *) &TK[6]));
258 PPK[4] += _S_(PPK[3] ^ Mk16_le((u16 *) &TK[8]));
259 PPK[5] += _S_(PPK[4] ^ Mk16_le((u16 *) &TK[10]));
261 PPK[0] += RotR1(PPK[5] ^ Mk16_le((u16 *) &TK[12]));
262 PPK[1] += RotR1(PPK[0] ^ Mk16_le((u16 *) &TK[14]));
263 PPK[2] += RotR1(PPK[1]);
264 PPK[3] += RotR1(PPK[2]);
265 PPK[4] += RotR1(PPK[3]);
266 PPK[5] += RotR1(PPK[4]);
268 /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value
269 * WEPSeed[0..2] is transmitted as WEP IV */
270 WEPSeed[0] = Hi8(IV16);
271 WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F;
272 WEPSeed[2] = Lo8(IV16);
273 WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((u16 *) &TK[0])) >> 1);
278 for (i = 0; i < 6; i++)
279 PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8);
285 static int hostap_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
287 struct hostap_tkip_data *tkey = priv;
289 u8 rc4key[16], *pos, *icv;
290 struct hostap_ieee80211_hdr *hdr;
292 struct scatterlist sg;
294 if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 ||
298 hdr = (struct hostap_ieee80211_hdr *) skb->data;
299 if (!tkey->tx_phase1_done) {
300 tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
302 tkey->tx_phase1_done = 1;
304 tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);
306 len = skb->len - hdr_len;
307 pos = skb_push(skb, 8);
308 memmove(pos, pos + 8, hdr_len);
310 icv = skb_put(skb, 4);
315 *pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */;
316 *pos++ = tkey->tx_iv32 & 0xff;
317 *pos++ = (tkey->tx_iv32 >> 8) & 0xff;
318 *pos++ = (tkey->tx_iv32 >> 16) & 0xff;
319 *pos++ = (tkey->tx_iv32 >> 24) & 0xff;
321 crc = ~crc32_le(~0, pos, len);
327 crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
328 sg.page = virt_to_page(pos);
329 sg.offset = offset_in_page(pos);
331 crypto_cipher_encrypt(tkey->tfm_arc4, &sg, &sg, len + 4);
334 if (tkey->tx_iv16 == 0) {
335 tkey->tx_phase1_done = 0;
343 static int hostap_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
345 struct hostap_tkip_data *tkey = priv;
347 u8 keyidx, *pos, icv[4];
350 struct hostap_ieee80211_hdr *hdr;
352 struct scatterlist sg;
355 if (skb->len < hdr_len + 8 + 4)
358 hdr = (struct hostap_ieee80211_hdr *) skb->data;
359 pos = skb->data + hdr_len;
361 if (!(keyidx & (1 << 5))) {
362 if (net_ratelimit()) {
363 printk(KERN_DEBUG "TKIP: received packet without ExtIV"
364 " flag from " MACSTR "\n", MAC2STR(hdr->addr2));
369 if (tkey->key_idx != keyidx) {
370 printk(KERN_DEBUG "TKIP: RX tkey->key_idx=%d frame "
371 "keyidx=%d priv=%p\n", tkey->key_idx, keyidx, priv);
374 if (!tkey->key_set) {
375 if (net_ratelimit()) {
376 printk(KERN_DEBUG "TKIP: received packet from " MACSTR
377 " with keyid=%d that does not have a configured"
378 " key\n", MAC2STR(hdr->addr2), keyidx);
382 iv16 = (pos[0] << 8) | pos[2];
383 iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
386 if (iv32 < tkey->rx_iv32 ||
387 (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {
388 if (net_ratelimit()) {
389 printk(KERN_DEBUG "TKIP: replay detected: STA=" MACSTR
390 " previous TSC %08x%04x received TSC "
391 "%08x%04x\n", MAC2STR(hdr->addr2),
392 tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
394 tkey->dot11RSNAStatsTKIPReplays++;
398 if (iv32 != tkey->rx_iv32 || !tkey->rx_phase1_done) {
399 tkip_mixing_phase1(tkey->rx_ttak, tkey->key, hdr->addr2, iv32);
400 tkey->rx_phase1_done = 1;
402 tkip_mixing_phase2(rc4key, tkey->key, tkey->rx_ttak, iv16);
404 plen = skb->len - hdr_len - 12;
406 crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
407 sg.page = virt_to_page(pos);
408 sg.offset = offset_in_page(pos);
409 sg.length = plen + 4;
410 crypto_cipher_decrypt(tkey->tfm_arc4, &sg, &sg, plen + 4);
412 crc = ~crc32_le(~0, pos, plen);
417 if (memcmp(icv, pos + plen, 4) != 0) {
418 if (iv32 != tkey->rx_iv32) {
419 /* Previously cached Phase1 result was already lost, so
420 * it needs to be recalculated for the next packet. */
421 tkey->rx_phase1_done = 0;
423 if (net_ratelimit()) {
424 printk(KERN_DEBUG "TKIP: ICV error detected: STA="
425 MACSTR "\n", MAC2STR(hdr->addr2));
427 tkey->dot11RSNAStatsTKIPICVErrors++;
431 /* Update real counters only after Michael MIC verification has
433 tkey->rx_iv32_new = iv32;
434 tkey->rx_iv16_new = iv16;
436 /* Remove IV and ICV */
437 memmove(skb->data + 8, skb->data, hdr_len);
439 skb_trim(skb, skb->len - 4);
445 static int michael_mic(struct hostap_tkip_data *tkey, u8 *key, u8 *hdr,
446 u8 *data, size_t data_len, u8 *mic)
448 struct scatterlist sg[2];
450 if (tkey->tfm_michael == NULL) {
451 printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
454 sg[0].page = virt_to_page(hdr);
455 sg[0].offset = offset_in_page(hdr);
458 sg[1].page = virt_to_page(data);
459 sg[1].offset = offset_in_page(data);
460 sg[1].length = data_len;
462 crypto_digest_init(tkey->tfm_michael);
463 crypto_digest_setkey(tkey->tfm_michael, key, 8);
464 crypto_digest_update(tkey->tfm_michael, sg, 2);
465 crypto_digest_final(tkey->tfm_michael, mic);
471 static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr)
473 struct hostap_ieee80211_hdr *hdr11;
475 hdr11 = (struct hostap_ieee80211_hdr *) skb->data;
476 switch (le16_to_cpu(hdr11->frame_control) &
477 (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
479 memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
480 memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
483 memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
484 memcpy(hdr + ETH_ALEN, hdr11->addr3, ETH_ALEN); /* SA */
486 case WLAN_FC_FROMDS | WLAN_FC_TODS:
487 memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
488 memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */
491 memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
492 memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
496 hdr[12] = 0; /* priority */
497 hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */
501 static int hostap_michael_mic_add(struct sk_buff *skb, int hdr_len, void *priv)
503 struct hostap_tkip_data *tkey = priv;
506 if (skb_tailroom(skb) < 8 || skb->len < hdr_len) {
507 printk(KERN_DEBUG "Invalid packet for Michael MIC add "
508 "(tailroom=%d hdr_len=%d skb->len=%d)\n",
509 skb_tailroom(skb), hdr_len, skb->len);
513 michael_mic_hdr(skb, tkey->tx_hdr);
514 pos = skb_put(skb, 8);
515 if (michael_mic(tkey, &tkey->key[16], tkey->tx_hdr,
516 skb->data + hdr_len, skb->len - 8 - hdr_len, pos))
523 static void hostap_michael_mic_failure(struct net_device *dev,
524 struct hostap_ieee80211_hdr *hdr,
527 union iwreq_data wrqu;
530 /* TODO: needed parameters: count, keyid, key type, src address, TSC */
531 sprintf(buf, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr="
532 MACSTR ")", keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni",
533 MAC2STR(hdr->addr2));
534 memset(&wrqu, 0, sizeof(wrqu));
535 wrqu.data.length = strlen(buf);
536 wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
540 static int hostap_michael_mic_verify(struct sk_buff *skb, int keyidx,
541 int hdr_len, void *priv)
543 struct hostap_tkip_data *tkey = priv;
549 michael_mic_hdr(skb, tkey->rx_hdr);
550 if (michael_mic(tkey, &tkey->key[24], tkey->rx_hdr,
551 skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
553 if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
554 struct hostap_ieee80211_hdr *hdr;
555 hdr = (struct hostap_ieee80211_hdr *) skb->data;
556 printk(KERN_DEBUG "%s: Michael MIC verification failed for "
557 "MSDU from " MACSTR " keyidx=%d\n",
558 skb->dev ? skb->dev->name : "N/A", MAC2STR(hdr->addr2),
561 hostap_michael_mic_failure(skb->dev, hdr, keyidx);
562 tkey->dot11RSNAStatsTKIPLocalMICFailures++;
566 /* Update TSC counters for RX now that the packet verification has
568 tkey->rx_iv32 = tkey->rx_iv32_new;
569 tkey->rx_iv16 = tkey->rx_iv16_new;
571 skb_trim(skb, skb->len - 8);
577 static int hostap_tkip_set_key(void *key, int len, u8 *seq, void *priv)
579 struct hostap_tkip_data *tkey = priv;
581 struct crypto_tfm *tfm = tkey->tfm_michael;
582 struct crypto_tfm *tfm2 = tkey->tfm_arc4;
584 keyidx = tkey->key_idx;
585 memset(tkey, 0, sizeof(*tkey));
586 tkey->key_idx = keyidx;
587 tkey->tfm_michael = tfm;
588 tkey->tfm_arc4 = tfm2;
589 if (len == TKIP_KEY_LEN) {
590 memcpy(tkey->key, key, TKIP_KEY_LEN);
592 tkey->tx_iv16 = 1; /* TSC is initialized to 1 */
594 tkey->rx_iv32 = (seq[5] << 24) | (seq[4] << 16) |
595 (seq[3] << 8) | seq[2];
596 tkey->rx_iv16 = (seq[1] << 8) | seq[0];
598 } else if (len == 0) {
607 static int hostap_tkip_get_key(void *key, int len, u8 *seq, void *priv)
609 struct hostap_tkip_data *tkey = priv;
611 if (len < TKIP_KEY_LEN)
616 memcpy(key, tkey->key, TKIP_KEY_LEN);
619 /* Return the sequence number of the last transmitted frame. */
620 u16 iv16 = tkey->tx_iv16;
621 u32 iv32 = tkey->tx_iv32;
625 seq[0] = tkey->tx_iv16;
626 seq[1] = tkey->tx_iv16 >> 8;
627 seq[2] = tkey->tx_iv32;
628 seq[3] = tkey->tx_iv32 >> 8;
629 seq[4] = tkey->tx_iv32 >> 16;
630 seq[5] = tkey->tx_iv32 >> 24;
637 static char * hostap_tkip_print_stats(char *p, void *priv)
639 struct hostap_tkip_data *tkip = priv;
640 p += sprintf(p, "key[%d] alg=TKIP key_set=%d "
641 "tx_pn=%02x%02x%02x%02x%02x%02x "
642 "rx_pn=%02x%02x%02x%02x%02x%02x "
643 "replays=%d icv_errors=%d local_mic_failures=%d\n",
644 tkip->key_idx, tkip->key_set,
645 (tkip->tx_iv32 >> 24) & 0xff,
646 (tkip->tx_iv32 >> 16) & 0xff,
647 (tkip->tx_iv32 >> 8) & 0xff,
648 tkip->tx_iv32 & 0xff,
649 (tkip->tx_iv16 >> 8) & 0xff,
650 tkip->tx_iv16 & 0xff,
651 (tkip->rx_iv32 >> 24) & 0xff,
652 (tkip->rx_iv32 >> 16) & 0xff,
653 (tkip->rx_iv32 >> 8) & 0xff,
654 tkip->rx_iv32 & 0xff,
655 (tkip->rx_iv16 >> 8) & 0xff,
656 tkip->rx_iv16 & 0xff,
657 tkip->dot11RSNAStatsTKIPReplays,
658 tkip->dot11RSNAStatsTKIPICVErrors,
659 tkip->dot11RSNAStatsTKIPLocalMICFailures);
664 static struct hostap_crypto_ops hostap_crypt_tkip = {
666 .init = hostap_tkip_init,
667 .deinit = hostap_tkip_deinit,
668 .encrypt_mpdu = hostap_tkip_encrypt,
669 .decrypt_mpdu = hostap_tkip_decrypt,
670 .encrypt_msdu = hostap_michael_mic_add,
671 .decrypt_msdu = hostap_michael_mic_verify,
672 .set_key = hostap_tkip_set_key,
673 .get_key = hostap_tkip_get_key,
674 .print_stats = hostap_tkip_print_stats,
675 .extra_prefix_len = 4 + 4 /* IV + ExtIV */,
676 .extra_postfix_len = 8 + 4 /* MIC + ICV */
680 static int __init hostap_crypto_tkip_init(void)
682 if (hostap_register_crypto_ops(&hostap_crypt_tkip) < 0)
689 static void __exit hostap_crypto_tkip_exit(void)
691 hostap_unregister_crypto_ops(&hostap_crypt_tkip);
695 module_init(hostap_crypto_tkip_init);
696 module_exit(hostap_crypto_tkip_exit);