1 // SPDX-License-Identifier: GPL-2.0
3 * Host AP crypt: host-based TKIP encryption implementation for Host AP driver
5 * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
8 #include <crypto/arc4.h>
9 #include <crypto/hash.h>
10 #include <linux/fips.h>
11 #include <linux/module.h>
12 #include <linux/init.h>
13 #include <linux/slab.h>
14 #include <linux/random.h>
15 #include <linux/skbuff.h>
16 #include <linux/netdevice.h>
17 #include <linux/if_ether.h>
18 #include <linux/if_arp.h>
19 #include <linux/string.h>
20 #include <linux/crc32.h>
21 #include <linux/etherdevice.h>
25 struct rtllib_tkip_data {
26 #define TKIP_KEY_LEN 32
43 u32 dot11RSNAStatsTKIPReplays;
44 u32 dot11RSNAStatsTKIPICVErrors;
45 u32 dot11RSNAStatsTKIPLocalMICFailures;
48 struct arc4_ctx rx_ctx_arc4;
49 struct arc4_ctx tx_ctx_arc4;
50 struct crypto_shash *rx_tfm_michael;
51 struct crypto_shash *tx_tfm_michael;
52 /* scratch buffers for virt_to_page() (crypto API) */
57 static void *rtllib_tkip_init(int key_idx)
59 struct rtllib_tkip_data *priv;
64 priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
67 priv->key_idx = key_idx;
69 priv->tx_tfm_michael = crypto_alloc_shash("michael_mic", 0, 0);
70 if (IS_ERR(priv->tx_tfm_michael)) {
71 pr_debug("Could not allocate crypto API michael_mic\n");
72 priv->tx_tfm_michael = NULL;
76 priv->rx_tfm_michael = crypto_alloc_shash("michael_mic", 0, 0);
77 if (IS_ERR(priv->rx_tfm_michael)) {
78 pr_debug("Could not allocate crypto API michael_mic\n");
79 priv->rx_tfm_michael = NULL;
86 crypto_free_shash(priv->tx_tfm_michael);
87 crypto_free_shash(priv->rx_tfm_michael);
94 static void rtllib_tkip_deinit(void *priv)
96 struct rtllib_tkip_data *_priv = priv;
99 crypto_free_shash(_priv->tx_tfm_michael);
100 crypto_free_shash(_priv->rx_tfm_michael);
102 kfree_sensitive(priv);
105 static inline u16 RotR1(u16 val)
107 return (val >> 1) | (val << 15);
110 static inline u8 Lo8(u16 val)
115 static inline u8 Hi8(u16 val)
120 static inline u16 Lo16(u32 val)
125 static inline u16 Hi16(u32 val)
130 static inline u16 Mk16(u8 hi, u8 lo)
132 return lo | (hi << 8);
135 static inline u16 Mk16_le(u16 *v)
140 static const u16 Sbox[256] = {
141 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
142 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
143 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
144 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
145 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
146 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
147 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
148 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
149 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
150 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
151 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
152 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
153 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
154 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
155 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
156 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
157 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
158 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
159 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
160 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
161 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
162 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
163 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
164 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
165 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
166 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
167 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
168 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
169 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
170 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
171 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
172 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
175 static inline u16 _S_(u16 v)
177 u16 t = Sbox[Hi8(v)];
178 return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8));
181 #define PHASE1_LOOP_COUNT 8
183 static void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32)
187 /* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */
188 TTAK[0] = Lo16(IV32);
189 TTAK[1] = Hi16(IV32);
190 TTAK[2] = Mk16(TA[1], TA[0]);
191 TTAK[3] = Mk16(TA[3], TA[2]);
192 TTAK[4] = Mk16(TA[5], TA[4]);
194 for (i = 0; i < PHASE1_LOOP_COUNT; i++) {
196 TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j]));
197 TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j]));
198 TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j]));
199 TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j]));
200 TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i;
204 static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK,
207 /* Make temporary area overlap WEP seed so that the final copy can be
208 * avoided on little endian hosts.
210 u16 *PPK = (u16 *)&WEPSeed[4];
212 /* Step 1 - make copy of TTAK and bring in TSC */
218 PPK[5] = TTAK[4] + IV16;
220 /* Step 2 - 96-bit bijective mixing using S-box */
221 PPK[0] += _S_(PPK[5] ^ Mk16_le((u16 *)&TK[0]));
222 PPK[1] += _S_(PPK[0] ^ Mk16_le((u16 *)&TK[2]));
223 PPK[2] += _S_(PPK[1] ^ Mk16_le((u16 *)&TK[4]));
224 PPK[3] += _S_(PPK[2] ^ Mk16_le((u16 *)&TK[6]));
225 PPK[4] += _S_(PPK[3] ^ Mk16_le((u16 *)&TK[8]));
226 PPK[5] += _S_(PPK[4] ^ Mk16_le((u16 *)&TK[10]));
228 PPK[0] += RotR1(PPK[5] ^ Mk16_le((u16 *)&TK[12]));
229 PPK[1] += RotR1(PPK[0] ^ Mk16_le((u16 *)&TK[14]));
230 PPK[2] += RotR1(PPK[1]);
231 PPK[3] += RotR1(PPK[2]);
232 PPK[4] += RotR1(PPK[3]);
233 PPK[5] += RotR1(PPK[4]);
235 /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value
236 * WEPSeed[0..2] is transmitted as WEP IV
238 WEPSeed[0] = Hi8(IV16);
239 WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F;
240 WEPSeed[2] = Lo8(IV16);
241 WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((u16 *)&TK[0])) >> 1);
247 for (i = 0; i < 6; i++)
248 PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8);
253 static int rtllib_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
255 struct rtllib_tkip_data *tkey = priv;
258 struct ieee80211_hdr *hdr;
259 struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb +
265 if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 ||
269 hdr = (struct ieee80211_hdr *)skb->data;
271 if (!tcb_desc->bHwSec) {
272 if (!tkey->tx_phase1_done) {
273 tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
275 tkey->tx_phase1_done = 1;
277 tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak,
280 tkey->tx_phase1_done = 1;
283 len = skb->len - hdr_len;
284 pos = skb_push(skb, 8);
285 memmove(pos, pos + 8, hdr_len);
288 if (tcb_desc->bHwSec) {
289 *pos++ = Hi8(tkey->tx_iv16);
290 *pos++ = (Hi8(tkey->tx_iv16) | 0x20) & 0x7F;
291 *pos++ = Lo8(tkey->tx_iv16);
298 *pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */;
299 *pos++ = tkey->tx_iv32 & 0xff;
300 *pos++ = (tkey->tx_iv32 >> 8) & 0xff;
301 *pos++ = (tkey->tx_iv32 >> 16) & 0xff;
302 *pos++ = (tkey->tx_iv32 >> 24) & 0xff;
304 if (!tcb_desc->bHwSec) {
305 icv = skb_put(skb, 4);
306 crc = ~crc32_le(~0, pos, len);
312 arc4_setkey(&tkey->tx_ctx_arc4, rc4key, 16);
313 arc4_crypt(&tkey->tx_ctx_arc4, pos, pos, len + 4);
317 if (tkey->tx_iv16 == 0) {
318 tkey->tx_phase1_done = 0;
322 if (!tcb_desc->bHwSec)
327 static int rtllib_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
329 struct rtllib_tkip_data *tkey = priv;
333 struct ieee80211_hdr *hdr;
334 struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb +
341 if (skb->len < hdr_len + 8 + 4)
344 hdr = (struct ieee80211_hdr *)skb->data;
345 pos = skb->data + hdr_len;
347 if (!(keyidx & (1 << 5))) {
348 if (net_ratelimit()) {
350 "Received packet without ExtIV flag from %pM\n",
356 if (tkey->key_idx != keyidx) {
358 "RX tkey->key_idx=%d frame keyidx=%d priv=%p\n",
359 tkey->key_idx, keyidx, priv);
362 if (!tkey->key_set) {
363 if (net_ratelimit()) {
365 "Received packet from %pM with keyid=%d that does not have a configured key\n",
370 iv16 = (pos[0] << 8) | pos[2];
371 iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
374 if (!tcb_desc->bHwSec || (skb->cb[0] == 1)) {
375 if ((iv32 < tkey->rx_iv32 ||
376 (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) &&
378 if (net_ratelimit()) {
380 "Replay detected: STA= %pM previous TSC %08x%04x received TSC %08x%04x\n",
381 hdr->addr2, tkey->rx_iv32,
382 tkey->rx_iv16, iv32, iv16);
384 tkey->dot11RSNAStatsTKIPReplays++;
387 tkey->initialized = true;
389 if (iv32 != tkey->rx_iv32 || !tkey->rx_phase1_done) {
390 tkip_mixing_phase1(tkey->rx_ttak, tkey->key,
392 tkey->rx_phase1_done = 1;
394 tkip_mixing_phase2(rc4key, tkey->key, tkey->rx_ttak, iv16);
396 plen = skb->len - hdr_len - 12;
398 arc4_setkey(&tkey->rx_ctx_arc4, rc4key, 16);
399 arc4_crypt(&tkey->rx_ctx_arc4, pos, pos, plen + 4);
401 crc = ~crc32_le(~0, pos, plen);
407 if (memcmp(icv, pos + plen, 4) != 0) {
408 if (iv32 != tkey->rx_iv32) {
409 /* Previously cached Phase1 result was already
410 * lost, so it needs to be recalculated for the
413 tkey->rx_phase1_done = 0;
415 if (net_ratelimit()) {
417 "ICV error detected: STA= %pM\n",
420 tkey->dot11RSNAStatsTKIPICVErrors++;
425 /* Update real counters only after Michael MIC verification has
428 tkey->rx_iv32_new = iv32;
429 tkey->rx_iv16_new = iv16;
431 /* Remove IV and ICV */
432 memmove(skb->data + 8, skb->data, hdr_len);
434 skb_trim(skb, skb->len - 4);
439 static int michael_mic(struct crypto_shash *tfm_michael, u8 *key, u8 *hdr,
440 u8 *data, size_t data_len, u8 *mic)
442 SHASH_DESC_ON_STACK(desc, tfm_michael);
445 desc->tfm = tfm_michael;
447 if (crypto_shash_setkey(tfm_michael, key, 8))
450 err = crypto_shash_init(desc);
453 err = crypto_shash_update(desc, hdr, 16);
456 err = crypto_shash_update(desc, data, data_len);
459 err = crypto_shash_final(desc, mic);
462 shash_desc_zero(desc);
466 static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr)
468 struct ieee80211_hdr *hdr11;
470 hdr11 = (struct ieee80211_hdr *)skb->data;
471 switch (le16_to_cpu(hdr11->frame_control) &
472 (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
473 case IEEE80211_FCTL_TODS:
474 ether_addr_copy(hdr, hdr11->addr3); /* DA */
475 ether_addr_copy(hdr + ETH_ALEN, hdr11->addr2); /* SA */
477 case IEEE80211_FCTL_FROMDS:
478 ether_addr_copy(hdr, hdr11->addr1); /* DA */
479 ether_addr_copy(hdr + ETH_ALEN, hdr11->addr3); /* SA */
481 case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
482 ether_addr_copy(hdr, hdr11->addr3); /* DA */
483 ether_addr_copy(hdr + ETH_ALEN, hdr11->addr4); /* SA */
486 ether_addr_copy(hdr, hdr11->addr1); /* DA */
487 ether_addr_copy(hdr + ETH_ALEN, hdr11->addr2); /* SA */
500 static int rtllib_michael_mic_add(struct sk_buff *skb, int hdr_len, void *priv)
502 struct rtllib_tkip_data *tkey = priv;
504 struct ieee80211_hdr *hdr;
506 hdr = (struct ieee80211_hdr *)skb->data;
508 if (skb_tailroom(skb) < 8 || skb->len < hdr_len) {
510 "Invalid packet for Michael MIC add (tailroom=%d hdr_len=%d skb->len=%d)\n",
511 skb_tailroom(skb), hdr_len, skb->len);
515 michael_mic_hdr(skb, tkey->tx_hdr);
517 if (RTLLIB_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_control)))
518 tkey->tx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07;
519 pos = skb_put(skb, 8);
520 if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr,
521 skb->data + hdr_len, skb->len - 8 - hdr_len, pos))
527 static void rtllib_michael_mic_failure(struct net_device *dev,
528 struct ieee80211_hdr *hdr,
531 union iwreq_data wrqu;
532 struct iw_michaelmicfailure ev;
534 /* TODO: needed parameters: count, keyid, key type, TSC */
535 memset(&ev, 0, sizeof(ev));
536 ev.flags = keyidx & IW_MICFAILURE_KEY_ID;
537 if (hdr->addr1[0] & 0x01)
538 ev.flags |= IW_MICFAILURE_GROUP;
540 ev.flags |= IW_MICFAILURE_PAIRWISE;
541 ev.src_addr.sa_family = ARPHRD_ETHER;
542 ether_addr_copy(ev.src_addr.sa_data, hdr->addr2);
543 memset(&wrqu, 0, sizeof(wrqu));
544 wrqu.data.length = sizeof(ev);
545 wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev);
548 static int rtllib_michael_mic_verify(struct sk_buff *skb, int keyidx,
549 int hdr_len, void *priv)
551 struct rtllib_tkip_data *tkey = priv;
553 struct ieee80211_hdr *hdr;
555 hdr = (struct ieee80211_hdr *)skb->data;
560 michael_mic_hdr(skb, tkey->rx_hdr);
561 if (RTLLIB_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_control)))
562 tkey->rx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07;
564 if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr,
565 skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
568 if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
569 struct ieee80211_hdr *hdr;
571 hdr = (struct ieee80211_hdr *)skb->data;
573 "Michael MIC verification failed for MSDU from %pM keyidx=%d\n",
575 netdev_dbg(skb->dev, "%d\n",
576 memcmp(mic, skb->data + skb->len - 8, 8) != 0);
578 pr_info("skb->dev != NULL\n");
579 rtllib_michael_mic_failure(skb->dev, hdr, keyidx);
581 tkey->dot11RSNAStatsTKIPLocalMICFailures++;
585 /* Update TSC counters for RX now that the packet verification has
588 tkey->rx_iv32 = tkey->rx_iv32_new;
589 tkey->rx_iv16 = tkey->rx_iv16_new;
591 skb_trim(skb, skb->len - 8);
596 static int rtllib_tkip_set_key(void *key, int len, u8 *seq, void *priv)
598 struct rtllib_tkip_data *tkey = priv;
600 struct crypto_shash *tfm = tkey->tx_tfm_michael;
601 struct crypto_shash *tfm3 = tkey->rx_tfm_michael;
603 keyidx = tkey->key_idx;
604 memset(tkey, 0, sizeof(*tkey));
605 tkey->key_idx = keyidx;
606 tkey->tx_tfm_michael = tfm;
607 tkey->rx_tfm_michael = tfm3;
609 if (len == TKIP_KEY_LEN) {
610 memcpy(tkey->key, key, TKIP_KEY_LEN);
612 tkey->tx_iv16 = 1; /* TSC is initialized to 1 */
614 tkey->rx_iv32 = (seq[5] << 24) | (seq[4] << 16) |
615 (seq[3] << 8) | seq[2];
616 tkey->rx_iv16 = (seq[1] << 8) | seq[0];
618 } else if (len == 0) {
627 static int rtllib_tkip_get_key(void *key, int len, u8 *seq, void *priv)
629 struct rtllib_tkip_data *tkey = priv;
631 if (len < TKIP_KEY_LEN)
636 memcpy(key, tkey->key, TKIP_KEY_LEN);
639 /* Return the sequence number of the last transmitted frame. */
640 u16 iv16 = tkey->tx_iv16;
641 u32 iv32 = tkey->tx_iv32;
646 seq[0] = tkey->tx_iv16;
647 seq[1] = tkey->tx_iv16 >> 8;
648 seq[2] = tkey->tx_iv32;
649 seq[3] = tkey->tx_iv32 >> 8;
650 seq[4] = tkey->tx_iv32 >> 16;
651 seq[5] = tkey->tx_iv32 >> 24;
657 static void rtllib_tkip_print_stats(struct seq_file *m, void *priv)
659 struct rtllib_tkip_data *tkip = priv;
662 "key[%d] alg=TKIP key_set=%d tx_pn=%02x%02x%02x%02x%02x%02x rx_pn=%02x%02x%02x%02x%02x%02x replays=%d icv_errors=%d local_mic_failures=%d\n",
663 tkip->key_idx, tkip->key_set,
664 (tkip->tx_iv32 >> 24) & 0xff,
665 (tkip->tx_iv32 >> 16) & 0xff,
666 (tkip->tx_iv32 >> 8) & 0xff,
667 tkip->tx_iv32 & 0xff,
668 (tkip->tx_iv16 >> 8) & 0xff,
669 tkip->tx_iv16 & 0xff,
670 (tkip->rx_iv32 >> 24) & 0xff,
671 (tkip->rx_iv32 >> 16) & 0xff,
672 (tkip->rx_iv32 >> 8) & 0xff,
673 tkip->rx_iv32 & 0xff,
674 (tkip->rx_iv16 >> 8) & 0xff,
675 tkip->rx_iv16 & 0xff,
676 tkip->dot11RSNAStatsTKIPReplays,
677 tkip->dot11RSNAStatsTKIPICVErrors,
678 tkip->dot11RSNAStatsTKIPLocalMICFailures);
681 static struct lib80211_crypto_ops rtllib_crypt_tkip = {
683 .init = rtllib_tkip_init,
684 .deinit = rtllib_tkip_deinit,
685 .encrypt_mpdu = rtllib_tkip_encrypt,
686 .decrypt_mpdu = rtllib_tkip_decrypt,
687 .encrypt_msdu = rtllib_michael_mic_add,
688 .decrypt_msdu = rtllib_michael_mic_verify,
689 .set_key = rtllib_tkip_set_key,
690 .get_key = rtllib_tkip_get_key,
691 .print_stats = rtllib_tkip_print_stats,
692 .extra_mpdu_prefix_len = 4 + 4, /* IV + ExtIV */
693 .extra_mpdu_postfix_len = 4, /* ICV */
694 .extra_msdu_postfix_len = 8, /* MIC */
695 .owner = THIS_MODULE,
698 static int __init rtllib_crypto_tkip_init(void)
700 return lib80211_register_crypto_ops(&rtllib_crypt_tkip);
703 static void __exit rtllib_crypto_tkip_exit(void)
705 lib80211_unregister_crypto_ops(&rtllib_crypt_tkip);
708 module_init(rtllib_crypto_tkip_init);
709 module_exit(rtllib_crypto_tkip_exit);
711 MODULE_LICENSE("GPL");