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 <asm/string.h>
24 #include "ieee80211.h"
26 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
27 #include "rtl_crypto.h"
29 #include <linux/crypto.h>
31 //#include <asm/scatterlist.h>
32 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
33 #include <asm/scatterlist.h>
35 #include <linux/scatterlist.h>
38 #include <linux/crc32.h>
40 MODULE_AUTHOR("Jouni Malinen");
41 MODULE_DESCRIPTION("Host AP crypt: TKIP");
42 MODULE_LICENSE("GPL");
45 #ifndef IN_OPENSUSE_SLED
46 #define IN_OPENSUSE_SLED 1
50 struct ieee80211_tkip_data {
51 #define TKIP_KEY_LEN 32
67 u32 dot11RSNAStatsTKIPReplays;
68 u32 dot11RSNAStatsTKIPICVErrors;
69 u32 dot11RSNAStatsTKIPLocalMICFailures;
73 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21))||(IN_OPENSUSE_SLED))
74 struct crypto_blkcipher *rx_tfm_arc4;
75 struct crypto_hash *rx_tfm_michael;
76 struct crypto_blkcipher *tx_tfm_arc4;
77 struct crypto_hash *tx_tfm_michael;
80 struct crypto_tfm *tfm_arc4;
81 struct crypto_tfm *tfm_michael;
83 /* scratch buffers for virt_to_page() (crypto API) */
84 u8 rx_hdr[16], tx_hdr[16];
87 static void * ieee80211_tkip_init(int key_idx)
89 struct ieee80211_tkip_data *priv;
91 priv = kmalloc(sizeof(*priv), GFP_ATOMIC);
94 memset(priv, 0, sizeof(*priv));
95 priv->key_idx = key_idx;
97 #if((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21))&&(!IN_OPENSUSE_SLED))
98 priv->tfm_arc4 = crypto_alloc_tfm("arc4", 0);
99 if (priv->tfm_arc4 == NULL) {
100 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
101 "crypto API arc4\n");
105 priv->tfm_michael = crypto_alloc_tfm("michael_mic", 0);
106 if (priv->tfm_michael == NULL) {
107 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
108 "crypto API michael_mic\n");
113 priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
115 if (IS_ERR(priv->tx_tfm_arc4)) {
116 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
117 "crypto API arc4\n");
118 priv->tx_tfm_arc4 = NULL;
122 priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
124 if (IS_ERR(priv->tx_tfm_michael)) {
125 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
126 "crypto API michael_mic\n");
127 priv->tx_tfm_michael = NULL;
131 priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
133 if (IS_ERR(priv->rx_tfm_arc4)) {
134 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
135 "crypto API arc4\n");
136 priv->rx_tfm_arc4 = NULL;
140 priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
142 if (IS_ERR(priv->rx_tfm_michael)) {
143 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
144 "crypto API michael_mic\n");
145 priv->rx_tfm_michael = NULL;
153 #if((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21))&&(!IN_OPENSUSE_SLED))
154 if (priv->tfm_michael)
155 crypto_free_tfm(priv->tfm_michael);
157 crypto_free_tfm(priv->tfm_arc4);
159 if (priv->tx_tfm_michael)
160 crypto_free_hash(priv->tx_tfm_michael);
161 if (priv->tx_tfm_arc4)
162 crypto_free_blkcipher(priv->tx_tfm_arc4);
163 if (priv->rx_tfm_michael)
164 crypto_free_hash(priv->rx_tfm_michael);
165 if (priv->rx_tfm_arc4)
166 crypto_free_blkcipher(priv->rx_tfm_arc4);
175 static void ieee80211_tkip_deinit(void *priv)
177 struct ieee80211_tkip_data *_priv = priv;
178 #if((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21))&&(!IN_OPENSUSE_SLED))
179 if (_priv && _priv->tfm_michael)
180 crypto_free_tfm(_priv->tfm_michael);
181 if (_priv && _priv->tfm_arc4)
182 crypto_free_tfm(_priv->tfm_arc4);
185 if (_priv->tx_tfm_michael)
186 crypto_free_hash(_priv->tx_tfm_michael);
187 if (_priv->tx_tfm_arc4)
188 crypto_free_blkcipher(_priv->tx_tfm_arc4);
189 if (_priv->rx_tfm_michael)
190 crypto_free_hash(_priv->rx_tfm_michael);
191 if (_priv->rx_tfm_arc4)
192 crypto_free_blkcipher(_priv->rx_tfm_arc4);
199 static inline u16 RotR1(u16 val)
201 return (val >> 1) | (val << 15);
205 static inline u8 Lo8(u16 val)
211 static inline u8 Hi8(u16 val)
217 static inline u16 Lo16(u32 val)
223 static inline u16 Hi16(u32 val)
229 static inline u16 Mk16(u8 hi, u8 lo)
231 return lo | (((u16) hi) << 8);
235 static inline u16 Mk16_le(u16 *v)
237 return le16_to_cpu(*v);
241 static const u16 Sbox[256] =
243 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
244 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
245 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
246 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
247 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
248 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
249 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
250 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
251 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
252 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
253 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
254 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
255 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
256 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
257 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
258 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
259 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
260 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
261 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
262 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
263 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
264 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
265 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
266 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
267 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
268 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
269 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
270 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
271 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
272 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
273 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
274 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
278 static inline u16 _S_(u16 v)
280 u16 t = Sbox[Hi8(v)];
281 return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8));
285 #define PHASE1_LOOP_COUNT 8
287 static void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32)
291 /* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */
292 TTAK[0] = Lo16(IV32);
293 TTAK[1] = Hi16(IV32);
294 TTAK[2] = Mk16(TA[1], TA[0]);
295 TTAK[3] = Mk16(TA[3], TA[2]);
296 TTAK[4] = Mk16(TA[5], TA[4]);
298 for (i = 0; i < PHASE1_LOOP_COUNT; i++) {
300 TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j]));
301 TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j]));
302 TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j]));
303 TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j]));
304 TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i;
309 static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK,
312 /* Make temporary area overlap WEP seed so that the final copy can be
313 * avoided on little endian hosts. */
314 u16 *PPK = (u16 *) &WEPSeed[4];
316 /* Step 1 - make copy of TTAK and bring in TSC */
322 PPK[5] = TTAK[4] + IV16;
324 /* Step 2 - 96-bit bijective mixing using S-box */
325 PPK[0] += _S_(PPK[5] ^ Mk16_le((u16 *) &TK[0]));
326 PPK[1] += _S_(PPK[0] ^ Mk16_le((u16 *) &TK[2]));
327 PPK[2] += _S_(PPK[1] ^ Mk16_le((u16 *) &TK[4]));
328 PPK[3] += _S_(PPK[2] ^ Mk16_le((u16 *) &TK[6]));
329 PPK[4] += _S_(PPK[3] ^ Mk16_le((u16 *) &TK[8]));
330 PPK[5] += _S_(PPK[4] ^ Mk16_le((u16 *) &TK[10]));
332 PPK[0] += RotR1(PPK[5] ^ Mk16_le((u16 *) &TK[12]));
333 PPK[1] += RotR1(PPK[0] ^ Mk16_le((u16 *) &TK[14]));
334 PPK[2] += RotR1(PPK[1]);
335 PPK[3] += RotR1(PPK[2]);
336 PPK[4] += RotR1(PPK[3]);
337 PPK[5] += RotR1(PPK[4]);
339 /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value
340 * WEPSeed[0..2] is transmitted as WEP IV */
341 WEPSeed[0] = Hi8(IV16);
342 WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F;
343 WEPSeed[2] = Lo8(IV16);
344 WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((u16 *) &TK[0])) >> 1);
349 for (i = 0; i < 6; i++)
350 PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8);
355 static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
357 struct ieee80211_tkip_data *tkey = priv;
358 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21))||(IN_OPENSUSE_SLED))
359 struct blkcipher_desc desc = {.tfm = tkey->tx_tfm_arc4};
363 struct ieee80211_hdr *hdr;
367 struct scatterlist sg;
372 if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 ||
376 hdr = (struct ieee80211_hdr *) skb->data;
379 printk("%x|", ((u32*)tkey->key)[0]);
380 printk("%x|", ((u32*)tkey->key)[1]);
381 printk("%x|", ((u32*)tkey->key)[2]);
382 printk("%x|", ((u32*)tkey->key)[3]);
383 printk("%x|", ((u32*)tkey->key)[4]);
384 printk("%x|", ((u32*)tkey->key)[5]);
385 printk("%x|", ((u32*)tkey->key)[6]);
386 printk("%x\n", ((u32*)tkey->key)[7]);
390 if (!tkey->tx_phase1_done) {
391 tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
393 tkey->tx_phase1_done = 1;
395 tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);
398 tkey->tx_phase1_done = 1;
401 len = skb->len - hdr_len;
402 pos = skb_push(skb, 8);
403 memmove(pos, pos + 8, hdr_len);
407 *pos++ = Hi8(tkey->tx_iv16);
408 *pos++ = (Hi8(tkey->tx_iv16) | 0x20) & 0x7F;
409 *pos++ = Lo8(tkey->tx_iv16);
415 *pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */;
416 *pos++ = tkey->tx_iv32 & 0xff;
417 *pos++ = (tkey->tx_iv32 >> 8) & 0xff;
418 *pos++ = (tkey->tx_iv32 >> 16) & 0xff;
419 *pos++ = (tkey->tx_iv32 >> 24) & 0xff;
421 icv = skb_put(skb, 4);
422 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
423 crc = ~crc32_le(~0, pos, len);
425 crc = ~ether_crc_le(len, pos);
431 #if((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21))&&(!IN_OPENSUSE_SLED))
432 crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
433 sg.page = virt_to_page(pos);
434 sg.offset = offset_in_page(pos);
436 crypto_cipher_encrypt(tkey->tfm_arc4, &sg, &sg, len + 4);
438 crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);
439 #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
440 sg.page = virt_to_page(pos);
441 sg.offset = offset_in_page(pos);
444 sg_init_one(&sg, pos, len+4);
446 ret= crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
450 if (tkey->tx_iv16 == 0) {
451 tkey->tx_phase1_done = 0;
455 #if((LINUX_VERSION_CODE <KERNEL_VERSION(2,6,21))&&(!IN_OPENSUSE_SLED))
465 static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
467 struct ieee80211_tkip_data *tkey = priv;
468 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)) ||(IN_OPENSUSE_SLED))
469 struct blkcipher_desc desc = {.tfm = tkey->rx_tfm_arc4};
474 struct ieee80211_hdr *hdr;
478 struct scatterlist sg;
482 if (skb->len < hdr_len + 8 + 4)
485 hdr = (struct ieee80211_hdr *) skb->data;
486 pos = skb->data + hdr_len;
488 if (!(keyidx & (1 << 5))) {
489 if (net_ratelimit()) {
490 printk(KERN_DEBUG "TKIP: received packet without ExtIV"
491 " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2));
496 if (tkey->key_idx != keyidx) {
497 printk(KERN_DEBUG "TKIP: RX tkey->key_idx=%d frame "
498 "keyidx=%d priv=%p\n", tkey->key_idx, keyidx, priv);
501 if (!tkey->key_set) {
502 if (net_ratelimit()) {
503 printk(KERN_DEBUG "TKIP: received packet from " MAC_FMT
504 " with keyid=%d that does not have a configured"
505 " key\n", MAC_ARG(hdr->addr2), keyidx);
509 iv16 = (pos[0] << 8) | pos[2];
510 iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
514 if (iv32 < tkey->rx_iv32 ||
515 (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {
516 if (net_ratelimit()) {
517 printk(KERN_DEBUG "TKIP: replay detected: STA=" MAC_FMT
518 " previous TSC %08x%04x received TSC "
519 "%08x%04x\n", MAC_ARG(hdr->addr2),
520 tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
522 tkey->dot11RSNAStatsTKIPReplays++;
526 if (iv32 != tkey->rx_iv32 || !tkey->rx_phase1_done) {
527 tkip_mixing_phase1(tkey->rx_ttak, tkey->key, hdr->addr2, iv32);
528 tkey->rx_phase1_done = 1;
530 tkip_mixing_phase2(rc4key, tkey->key, tkey->rx_ttak, iv16);
532 plen = skb->len - hdr_len - 12;
533 #if((LINUX_VERSION_CODE <KERNEL_VERSION(2,6,21))&&(!IN_OPENSUSE_SLED))
534 crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
535 sg.page = virt_to_page(pos);
536 sg.offset = offset_in_page(pos);
537 sg.length = plen + 4;
538 crypto_cipher_decrypt(tkey->tfm_arc4, &sg, &sg, plen + 4);
540 crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
541 #if(LINUX_VERSION_CODE <KERNEL_VERSION(2,6,24))
542 sg.page = virt_to_page(pos);
543 sg.offset = offset_in_page(pos);
544 sg.length = plen + 4;
546 sg_init_one(&sg, pos, plen+4);
548 if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) {
549 if (net_ratelimit()) {
550 printk(KERN_DEBUG ": TKIP: failed to decrypt "
551 "received packet from " MAC_FMT "\n",
552 MAC_ARG(hdr->addr2));
558 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
559 crc = ~crc32_le(~0, pos, plen);
561 crc = ~ether_crc_le(plen, pos);
567 if (memcmp(icv, pos + plen, 4) != 0) {
568 if (iv32 != tkey->rx_iv32) {
569 /* Previously cached Phase1 result was already lost, so
570 * it needs to be recalculated for the next packet. */
571 tkey->rx_phase1_done = 0;
573 if (net_ratelimit()) {
574 printk(KERN_DEBUG "TKIP: ICV error detected: STA="
575 MAC_FMT "\n", MAC_ARG(hdr->addr2));
577 tkey->dot11RSNAStatsTKIPICVErrors++;
581 #endif /* JOHN_TKIP */
583 /* Update real counters only after Michael MIC verification has
585 tkey->rx_iv32_new = iv32;
586 tkey->rx_iv16_new = iv16;
588 /* Remove IV and ICV */
589 memmove(skb->data + 8, skb->data, hdr_len);
591 skb_trim(skb, skb->len - 4);
595 if( ((u16*)skb->data)[0] & 0x4000){
596 printk("@@ rx decrypted skb->data");
598 for(i=0;i<skb->len;i++){
599 if( (i%24)==0 ) printk("\n");
600 printk("%2x ", ((u8*)skb->data)[i]);
608 #if((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!IN_OPENSUSE_SLED))
609 static int michael_mic(struct ieee80211_tkip_data *tkey, u8 *key, u8 *hdr,
610 u8 *data, size_t data_len, u8 *mic)
612 struct scatterlist sg[2];
613 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
614 struct hash_desc desc;
617 if (tkey->tfm_michael == NULL) {
618 printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
621 sg[0].page = virt_to_page(hdr);
622 sg[0].offset = offset_in_page(hdr);
625 sg[1].page = virt_to_page(data);
626 sg[1].offset = offset_in_page(data);
627 sg[1].length = data_len;
629 //crypto_digest_init(tkey->tfm_michael);
630 //crypto_digest_setkey(tkey->tfm_michael, key, 8);
631 //crypto_digest_update(tkey->tfm_michael, sg, 2);
632 //crypto_digest_final(tkey->tfm_michael, mic);
635 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
636 crypto_digest_init(tkey->tfm_michael);
637 crypto_digest_setkey(tkey->tfm_michael, key, 8);
638 crypto_digest_update(tkey->tfm_michael, sg, 2);
639 crypto_digest_final(tkey->tfm_michael, mic);
643 if (crypto_hash_setkey(tkey->tfm_michael, key, 8))
647 desc.tfm = tkey->tfm_michael;
649 ret = crypto_hash_digest(&desc, sg, data_len + 16, mic);
654 static int michael_mic(struct crypto_hash *tfm_michael, u8 * key, u8 * hdr,
655 u8 * data, size_t data_len, u8 * mic)
657 struct hash_desc desc;
658 struct scatterlist sg[2];
660 if (tfm_michael == NULL) {
661 printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
664 #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
665 sg[0].page = virt_to_page(hdr);
666 sg[0].offset = offset_in_page(hdr);
668 sg[1].page = virt_to_page(data);
669 sg[1].offset = offset_in_page(data);
670 sg[1].length = data_len;
672 sg_init_table(sg, 2);
673 sg_set_buf(&sg[0], hdr, 16);
674 sg_set_buf(&sg[1], data, data_len);
677 if (crypto_hash_setkey(tfm_michael, key, 8))
680 desc.tfm = tfm_michael;
682 return crypto_hash_digest(&desc, sg, data_len + 16, mic);
688 static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr)
690 struct ieee80211_hdr *hdr11;
692 hdr11 = (struct ieee80211_hdr *) skb->data;
693 switch (le16_to_cpu(hdr11->frame_ctl) &
694 (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
695 case IEEE80211_FCTL_TODS:
696 memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
697 memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
699 case IEEE80211_FCTL_FROMDS:
700 memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
701 memcpy(hdr + ETH_ALEN, hdr11->addr3, ETH_ALEN); /* SA */
703 case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
704 memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
705 memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */
708 memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
709 memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
713 hdr[12] = 0; /* priority */
715 hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */
719 static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len, void *priv)
721 struct ieee80211_tkip_data *tkey = priv;
723 struct ieee80211_hdr *hdr;
725 hdr = (struct ieee80211_hdr *) skb->data;
727 if (skb_tailroom(skb) < 8 || skb->len < hdr_len) {
728 printk(KERN_DEBUG "Invalid packet for Michael MIC add "
729 "(tailroom=%d hdr_len=%d skb->len=%d)\n",
730 skb_tailroom(skb), hdr_len, skb->len);
734 michael_mic_hdr(skb, tkey->tx_hdr);
737 // fix the wpa process with wmm enabled.
738 if(IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl))) {
739 tkey->tx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07;
742 pos = skb_put(skb, 8);
743 #if((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21))&&(!IN_OPENSUSE_SLED))
744 if (michael_mic(tkey, &tkey->key[16], tkey->tx_hdr,
745 skb->data + hdr_len, skb->len - 8 - hdr_len, pos))
747 if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr,
748 skb->data + hdr_len, skb->len - 8 - hdr_len, pos))
756 #if WIRELESS_EXT >= 18
757 static void ieee80211_michael_mic_failure(struct net_device *dev,
758 struct ieee80211_hdr *hdr,
761 union iwreq_data wrqu;
762 struct iw_michaelmicfailure ev;
764 /* TODO: needed parameters: count, keyid, key type, TSC */
765 memset(&ev, 0, sizeof(ev));
766 ev.flags = keyidx & IW_MICFAILURE_KEY_ID;
767 if (hdr->addr1[0] & 0x01)
768 ev.flags |= IW_MICFAILURE_GROUP;
770 ev.flags |= IW_MICFAILURE_PAIRWISE;
771 ev.src_addr.sa_family = ARPHRD_ETHER;
772 memcpy(ev.src_addr.sa_data, hdr->addr2, ETH_ALEN);
773 memset(&wrqu, 0, sizeof(wrqu));
774 wrqu.data.length = sizeof(ev);
775 wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *) &ev);
777 #elif WIRELESS_EXT >= 15
778 static void ieee80211_michael_mic_failure(struct net_device *dev,
779 struct ieee80211_hdr *hdr,
782 union iwreq_data wrqu;
785 /* TODO: needed parameters: count, keyid, key type, TSC */
786 sprintf(buf, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr="
787 MAC_FMT ")", keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni",
788 MAC_ARG(hdr->addr2));
789 memset(&wrqu, 0, sizeof(wrqu));
790 wrqu.data.length = strlen(buf);
791 wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
793 #else /* WIRELESS_EXT >= 15 */
794 static inline void ieee80211_michael_mic_failure(struct net_device *dev,
795 struct ieee80211_hdr *hdr,
799 #endif /* WIRELESS_EXT >= 15 */
802 static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
803 int hdr_len, void *priv)
805 struct ieee80211_tkip_data *tkey = priv;
807 struct ieee80211_hdr *hdr;
809 hdr = (struct ieee80211_hdr *) skb->data;
814 michael_mic_hdr(skb, tkey->rx_hdr);
816 // fix the wpa process with wmm enabled.
817 if(IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl))) {
818 tkey->rx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07;
821 #if((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21))&&(!IN_OPENSUSE_SLED))
822 if (michael_mic(tkey, &tkey->key[24], tkey->rx_hdr,
823 skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
825 if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr,
826 skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
829 if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
830 struct ieee80211_hdr *hdr;
831 hdr = (struct ieee80211_hdr *) skb->data;
832 printk(KERN_DEBUG "%s: Michael MIC verification failed for "
833 "MSDU from " MAC_FMT " keyidx=%d\n",
834 skb->dev ? skb->dev->name : "N/A", MAC_ARG(hdr->addr2),
837 ieee80211_michael_mic_failure(skb->dev, hdr, keyidx);
838 tkey->dot11RSNAStatsTKIPLocalMICFailures++;
842 /* Update TSC counters for RX now that the packet verification has
844 tkey->rx_iv32 = tkey->rx_iv32_new;
845 tkey->rx_iv16 = tkey->rx_iv16_new;
847 skb_trim(skb, skb->len - 8);
853 static int ieee80211_tkip_set_key(void *key, int len, u8 *seq, void *priv)
855 struct ieee80211_tkip_data *tkey = priv;
857 #if ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21))&&(!IN_OPENSUSE_SLED))
858 struct crypto_tfm *tfm = tkey->tfm_michael;
859 struct crypto_tfm *tfm2 = tkey->tfm_arc4;
861 struct crypto_hash *tfm = tkey->tx_tfm_michael;
862 struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4;
863 struct crypto_hash *tfm3 = tkey->rx_tfm_michael;
864 struct crypto_blkcipher *tfm4 = tkey->rx_tfm_arc4;
867 keyidx = tkey->key_idx;
868 memset(tkey, 0, sizeof(*tkey));
869 tkey->key_idx = keyidx;
871 #if((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21))&&(!IN_OPENSUSE_SLED))
872 tkey->tfm_michael = tfm;
873 tkey->tfm_arc4 = tfm2;
875 tkey->tx_tfm_michael = tfm;
876 tkey->tx_tfm_arc4 = tfm2;
877 tkey->rx_tfm_michael = tfm3;
878 tkey->rx_tfm_arc4 = tfm4;
881 if (len == TKIP_KEY_LEN) {
882 memcpy(tkey->key, key, TKIP_KEY_LEN);
884 tkey->tx_iv16 = 1; /* TSC is initialized to 1 */
886 tkey->rx_iv32 = (seq[5] << 24) | (seq[4] << 16) |
887 (seq[3] << 8) | seq[2];
888 tkey->rx_iv16 = (seq[1] << 8) | seq[0];
899 static int ieee80211_tkip_get_key(void *key, int len, u8 *seq, void *priv)
901 struct ieee80211_tkip_data *tkey = priv;
903 if (len < TKIP_KEY_LEN)
908 memcpy(key, tkey->key, TKIP_KEY_LEN);
911 /* Return the sequence number of the last transmitted frame. */
912 u16 iv16 = tkey->tx_iv16;
913 u32 iv32 = tkey->tx_iv32;
917 seq[0] = tkey->tx_iv16;
918 seq[1] = tkey->tx_iv16 >> 8;
919 seq[2] = tkey->tx_iv32;
920 seq[3] = tkey->tx_iv32 >> 8;
921 seq[4] = tkey->tx_iv32 >> 16;
922 seq[5] = tkey->tx_iv32 >> 24;
929 static char * ieee80211_tkip_print_stats(char *p, void *priv)
931 struct ieee80211_tkip_data *tkip = priv;
932 p += sprintf(p, "key[%d] alg=TKIP key_set=%d "
933 "tx_pn=%02x%02x%02x%02x%02x%02x "
934 "rx_pn=%02x%02x%02x%02x%02x%02x "
935 "replays=%d icv_errors=%d local_mic_failures=%d\n",
936 tkip->key_idx, tkip->key_set,
937 (tkip->tx_iv32 >> 24) & 0xff,
938 (tkip->tx_iv32 >> 16) & 0xff,
939 (tkip->tx_iv32 >> 8) & 0xff,
940 tkip->tx_iv32 & 0xff,
941 (tkip->tx_iv16 >> 8) & 0xff,
942 tkip->tx_iv16 & 0xff,
943 (tkip->rx_iv32 >> 24) & 0xff,
944 (tkip->rx_iv32 >> 16) & 0xff,
945 (tkip->rx_iv32 >> 8) & 0xff,
946 tkip->rx_iv32 & 0xff,
947 (tkip->rx_iv16 >> 8) & 0xff,
948 tkip->rx_iv16 & 0xff,
949 tkip->dot11RSNAStatsTKIPReplays,
950 tkip->dot11RSNAStatsTKIPICVErrors,
951 tkip->dot11RSNAStatsTKIPLocalMICFailures);
956 static struct ieee80211_crypto_ops ieee80211_crypt_tkip = {
958 .init = ieee80211_tkip_init,
959 .deinit = ieee80211_tkip_deinit,
960 .encrypt_mpdu = ieee80211_tkip_encrypt,
961 .decrypt_mpdu = ieee80211_tkip_decrypt,
962 .encrypt_msdu = ieee80211_michael_mic_add,
963 .decrypt_msdu = ieee80211_michael_mic_verify,
964 .set_key = ieee80211_tkip_set_key,
965 .get_key = ieee80211_tkip_get_key,
966 .print_stats = ieee80211_tkip_print_stats,
967 .extra_prefix_len = 4 + 4, /* IV + ExtIV */
968 .extra_postfix_len = 8 + 4, /* MIC + ICV */
969 .owner = THIS_MODULE,
973 int ieee80211_crypto_tkip_init(void)
975 return ieee80211_register_crypto_ops(&ieee80211_crypt_tkip);
979 void ieee80211_crypto_tkip_exit(void)
981 ieee80211_unregister_crypto_ops(&ieee80211_crypt_tkip);
985 void ieee80211_tkip_null(void)
987 // printk("============>%s()\n", __FUNCTION__);
992 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
993 EXPORT_SYMBOL(ieee80211_tkip_null);
995 EXPORT_SYMBOL_NOVERS(ieee80211_tkip_null);
1000 //module_init(ieee80211_crypto_tkip_init);
1001 //module_exit(ieee80211_crypto_tkip_exit);