18fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang/* 28fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang * Host AP crypt: host-based TKIP encryption implementation for Host AP driver 38fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang * 48fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi> 58fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang * 68fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang * This program is free software; you can redistribute it and/or modify 78fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang * it under the terms of the GNU General Public License version 2 as 88fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang * published by the Free Software Foundation. See README and COPYING for 98fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang * more details. 108fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang */ 118fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 128fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang//#include <linux/config.h> 138fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/module.h> 148fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/init.h> 158fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/slab.h> 168fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/random.h> 178fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/skbuff.h> 188fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/netdevice.h> 198fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/if_ether.h> 208fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/if_arp.h> 218fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <asm/string.h> 228fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 238fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include "ieee80211.h" 248fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 258fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/crypto.h> 26e406322b4b963e622f41d76193d8ca9e5435adb8Mauro Carvalho Chehab #include <linux/scatterlist.h> 278fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/crc32.h> 288fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 298fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry ChuangMODULE_AUTHOR("Jouni Malinen"); 308fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry ChuangMODULE_DESCRIPTION("Host AP crypt: TKIP"); 318fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry ChuangMODULE_LICENSE("GPL"); 328fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 338fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangstruct ieee80211_tkip_data { 348fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#define TKIP_KEY_LEN 32 358fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u8 key[TKIP_KEY_LEN]; 368fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang int key_set; 378fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 388fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u32 tx_iv32; 398fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u16 tx_iv16; 408fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u16 tx_ttak[5]; 418fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang int tx_phase1_done; 428fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 438fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u32 rx_iv32; 448fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u16 rx_iv16; 458fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u16 rx_ttak[5]; 468fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang int rx_phase1_done; 478fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u32 rx_iv32_new; 488fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u16 rx_iv16_new; 498fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 508fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u32 dot11RSNAStatsTKIPReplays; 518fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u32 dot11RSNAStatsTKIPICVErrors; 528fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u32 dot11RSNAStatsTKIPLocalMICFailures; 538fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 548fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang int key_idx; 55f61fb9356d20977258bb59a8d9f1857d2c58ac98Mauro Carvalho Chehab 568fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct crypto_blkcipher *rx_tfm_arc4; 578fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct crypto_hash *rx_tfm_michael; 588fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct crypto_blkcipher *tx_tfm_arc4; 598fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct crypto_hash *tx_tfm_michael; 60f61fb9356d20977258bb59a8d9f1857d2c58ac98Mauro Carvalho Chehab 618fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* scratch buffers for virt_to_page() (crypto API) */ 628fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u8 rx_hdr[16], tx_hdr[16]; 638fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang}; 648fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 658acfd58a4d53ff3724172e8fbd03c3ac97da5342Xenia Ragiadakoustatic void *ieee80211_tkip_init(int key_idx) 668fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 678fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ieee80211_tkip_data *priv; 688fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 697a6cb0d5497418599d2125b670926b75e673861cJulia Lawall priv = kzalloc(sizeof(*priv), GFP_ATOMIC); 708fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (priv == NULL) 718fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang goto fail; 728fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang priv->key_idx = key_idx; 738fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 748fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, 758fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang CRYPTO_ALG_ASYNC); 768fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (IS_ERR(priv->tx_tfm_arc4)) { 778fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " 788fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang "crypto API arc4\n"); 798fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang priv->tx_tfm_arc4 = NULL; 808fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang goto fail; 818fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 828fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 838fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0, 848fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang CRYPTO_ALG_ASYNC); 858fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (IS_ERR(priv->tx_tfm_michael)) { 868fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " 878fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang "crypto API michael_mic\n"); 888fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang priv->tx_tfm_michael = NULL; 898fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang goto fail; 908fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 918fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 928fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, 938fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang CRYPTO_ALG_ASYNC); 948fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (IS_ERR(priv->rx_tfm_arc4)) { 958fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " 968fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang "crypto API arc4\n"); 978fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang priv->rx_tfm_arc4 = NULL; 988fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang goto fail; 998fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 1008fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1018fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0, 1028fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang CRYPTO_ALG_ASYNC); 1038fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (IS_ERR(priv->rx_tfm_michael)) { 1048fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " 1058fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang "crypto API michael_mic\n"); 1068fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang priv->rx_tfm_michael = NULL; 1078fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang goto fail; 1088fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 109f61fb9356d20977258bb59a8d9f1857d2c58ac98Mauro Carvalho Chehab 1108fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return priv; 1118fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1128fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangfail: 1138fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (priv) { 1148fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (priv->tx_tfm_michael) 1158fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang crypto_free_hash(priv->tx_tfm_michael); 1168fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (priv->tx_tfm_arc4) 1178fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang crypto_free_blkcipher(priv->tx_tfm_arc4); 1188fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (priv->rx_tfm_michael) 1198fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang crypto_free_hash(priv->rx_tfm_michael); 1208fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (priv->rx_tfm_arc4) 1218fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang crypto_free_blkcipher(priv->rx_tfm_arc4); 1228fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang kfree(priv); 1238fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 1248fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1258fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return NULL; 1268fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 1278fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1288fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1298fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangstatic void ieee80211_tkip_deinit(void *priv) 1308fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 1318fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ieee80211_tkip_data *_priv = priv; 132f61fb9356d20977258bb59a8d9f1857d2c58ac98Mauro Carvalho Chehab 1338fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (_priv) { 1348fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (_priv->tx_tfm_michael) 1358fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang crypto_free_hash(_priv->tx_tfm_michael); 1368fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (_priv->tx_tfm_arc4) 1378fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang crypto_free_blkcipher(_priv->tx_tfm_arc4); 1388fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (_priv->rx_tfm_michael) 1398fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang crypto_free_hash(_priv->rx_tfm_michael); 1408fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (_priv->rx_tfm_arc4) 1418fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang crypto_free_blkcipher(_priv->rx_tfm_arc4); 1428fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 1438fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang kfree(priv); 1448fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 1458fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1468fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1478fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangstatic inline u16 RotR1(u16 val) 1488fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 1498fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return (val >> 1) | (val << 15); 1508fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 1518fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1528fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1538fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangstatic inline u8 Lo8(u16 val) 1548fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 1558fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return val & 0xff; 1568fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 1578fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1588fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1598fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangstatic inline u8 Hi8(u16 val) 1608fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 1618fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return val >> 8; 1628fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 1638fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1648fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1658fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangstatic inline u16 Lo16(u32 val) 1668fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 1678fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return val & 0xffff; 1688fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 1698fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1708fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1718fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangstatic inline u16 Hi16(u32 val) 1728fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 1738fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return val >> 16; 1748fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 1758fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1768fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1778fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangstatic inline u16 Mk16(u8 hi, u8 lo) 1788fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 1798fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return lo | (((u16) hi) << 8); 1808fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 1818fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1828fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1838fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangstatic inline u16 Mk16_le(u16 *v) 1848fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 1858fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return le16_to_cpu(*v); 1868fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 1878fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1888fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1898fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangstatic const u16 Sbox[256] = 1908fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 1918fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154, 1928fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A, 1938fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B, 1948fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B, 1958fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F, 1968fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F, 1978fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5, 1988fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F, 1998fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB, 2008fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397, 2018fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED, 2028fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A, 2038fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194, 2048fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3, 2058fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104, 2068fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D, 2078fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39, 2088fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695, 2098fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83, 2108fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76, 2118fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4, 2128fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B, 2138fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0, 2148fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018, 2158fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751, 2168fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85, 2178fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12, 2188fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9, 2198fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7, 2208fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A, 2218fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8, 2228fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A, 2238fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang}; 2248fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 2258fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 2268fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangstatic inline u16 _S_(u16 v) 2278fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 2288fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u16 t = Sbox[Hi8(v)]; 2298fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8)); 2308fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 2318fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 2328fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 2338fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#define PHASE1_LOOP_COUNT 8 2348fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 2358fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 2368fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangstatic void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32) 2378fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 2388fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang int i, j; 2398fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 2408fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */ 2418fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang TTAK[0] = Lo16(IV32); 2428fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang TTAK[1] = Hi16(IV32); 2438fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang TTAK[2] = Mk16(TA[1], TA[0]); 2448fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang TTAK[3] = Mk16(TA[3], TA[2]); 2458fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang TTAK[4] = Mk16(TA[5], TA[4]); 2468fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 2478fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang for (i = 0; i < PHASE1_LOOP_COUNT; i++) { 2488fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang j = 2 * (i & 1); 2498fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j])); 2508fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j])); 2518fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j])); 2528fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j])); 2538fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i; 2548fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 2558fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 2568fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 2578fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 2588fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangstatic void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK, 2598fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u16 IV16) 2608fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 2618fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* Make temporary area overlap WEP seed so that the final copy can be 2628fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang * avoided on little endian hosts. */ 2638fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u16 *PPK = (u16 *) &WEPSeed[4]; 2648fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 2658fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* Step 1 - make copy of TTAK and bring in TSC */ 2668fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang PPK[0] = TTAK[0]; 2678fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang PPK[1] = TTAK[1]; 2688fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang PPK[2] = TTAK[2]; 2698fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang PPK[3] = TTAK[3]; 2708fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang PPK[4] = TTAK[4]; 2718fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang PPK[5] = TTAK[4] + IV16; 2728fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 2738fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* Step 2 - 96-bit bijective mixing using S-box */ 2748fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang PPK[0] += _S_(PPK[5] ^ Mk16_le((u16 *) &TK[0])); 2758fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang PPK[1] += _S_(PPK[0] ^ Mk16_le((u16 *) &TK[2])); 2768fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang PPK[2] += _S_(PPK[1] ^ Mk16_le((u16 *) &TK[4])); 2778fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang PPK[3] += _S_(PPK[2] ^ Mk16_le((u16 *) &TK[6])); 2788fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang PPK[4] += _S_(PPK[3] ^ Mk16_le((u16 *) &TK[8])); 2798fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang PPK[5] += _S_(PPK[4] ^ Mk16_le((u16 *) &TK[10])); 2808fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 2818fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang PPK[0] += RotR1(PPK[5] ^ Mk16_le((u16 *) &TK[12])); 2828fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang PPK[1] += RotR1(PPK[0] ^ Mk16_le((u16 *) &TK[14])); 2838fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang PPK[2] += RotR1(PPK[1]); 2848fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang PPK[3] += RotR1(PPK[2]); 2858fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang PPK[4] += RotR1(PPK[3]); 2868fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang PPK[5] += RotR1(PPK[4]); 2878fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 2888fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value 2898fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang * WEPSeed[0..2] is transmitted as WEP IV */ 2908fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang WEPSeed[0] = Hi8(IV16); 2918fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F; 2928fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang WEPSeed[2] = Lo8(IV16); 2938fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((u16 *) &TK[0])) >> 1); 2948fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 2958fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#ifdef __BIG_ENDIAN 2968fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 2978fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang int i; 2988fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang for (i = 0; i < 6; i++) 2998fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8); 3008fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 3018fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#endif 3028fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 3038fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 3048fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 3058fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangstatic int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) 3068fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 3078fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ieee80211_tkip_data *tkey = priv; 3088fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang int len; 3098fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u8 *pos; 3108fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ieee80211_hdr_4addr *hdr; 3118fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); 3128fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct blkcipher_desc desc = {.tfm = tkey->tx_tfm_arc4}; 3138fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang int ret = 0; 3148fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u8 rc4key[16], *icv; 3158fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u32 crc; 3168fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct scatterlist sg; 3178fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 3188fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 || 3198fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang skb->len < hdr_len) 3208fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return -1; 3218fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 3228fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang hdr = (struct ieee80211_hdr_4addr *) skb->data; 3238fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 3248fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (!tcb_desc->bHwSec) 3258fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 3268fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (!tkey->tx_phase1_done) { 3278fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2, 3288fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->tx_iv32); 3298fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->tx_phase1_done = 1; 3308fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 3318fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16); 3328fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 3338fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang else 3348fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->tx_phase1_done = 1; 3358fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 3368fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 3378fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang len = skb->len - hdr_len; 3388fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang pos = skb_push(skb, 8); 3398fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memmove(pos, pos + 8, hdr_len); 3408fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang pos += hdr_len; 3418fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 3428fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (tcb_desc->bHwSec) 3438fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 3448fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang *pos++ = Hi8(tkey->tx_iv16); 3458fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang *pos++ = (Hi8(tkey->tx_iv16) | 0x20) & 0x7F; 3468fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang *pos++ = Lo8(tkey->tx_iv16); 3478fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 3488fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang else 3498fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 3508fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang *pos++ = rc4key[0]; 3518fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang *pos++ = rc4key[1]; 3528fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang *pos++ = rc4key[2]; 3538fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 3548fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 3558fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang *pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */; 3568fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang *pos++ = tkey->tx_iv32 & 0xff; 3578fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang *pos++ = (tkey->tx_iv32 >> 8) & 0xff; 3588fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang *pos++ = (tkey->tx_iv32 >> 16) & 0xff; 3598fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang *pos++ = (tkey->tx_iv32 >> 24) & 0xff; 3608fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 3618fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (!tcb_desc->bHwSec) 3628fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 3638fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang icv = skb_put(skb, 4); 3648fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang crc = ~crc32_le(~0, pos, len); 3658fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang icv[0] = crc; 3668fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang icv[1] = crc >> 8; 3678fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang icv[2] = crc >> 16; 3688fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang icv[3] = crc >> 24; 3698fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); 3708fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang sg_init_one(&sg, pos, len+4); 3718fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ret= crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); 3728fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 3738fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 3748fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->tx_iv16++; 3758fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (tkey->tx_iv16 == 0) { 3768fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->tx_phase1_done = 0; 3778fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->tx_iv32++; 3788fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 3798fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 3808fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (!tcb_desc->bHwSec) 3818fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return ret; 3828fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang else 383e406322b4b963e622f41d76193d8ca9e5435adb8Mauro Carvalho Chehab return 0; 3848fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 3858fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 3868fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 3878fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 3888fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangstatic int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) 3898fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 3908fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ieee80211_tkip_data *tkey = priv; 3918fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u8 keyidx, *pos; 3928fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u32 iv32; 3938fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u16 iv16; 3948fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ieee80211_hdr_4addr *hdr; 3958fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); 3968fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct blkcipher_desc desc = {.tfm = tkey->rx_tfm_arc4}; 3978fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u8 rc4key[16]; 3988fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u8 icv[4]; 3998fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u32 crc; 4008fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct scatterlist sg; 4018fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang int plen; 4028fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (skb->len < hdr_len + 8 + 4) 4038fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return -1; 4048fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 4058fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang hdr = (struct ieee80211_hdr_4addr *) skb->data; 4068fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang pos = skb->data + hdr_len; 4078fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang keyidx = pos[3]; 4088fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (!(keyidx & (1 << 5))) { 4098fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (net_ratelimit()) { 4108fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang printk(KERN_DEBUG "TKIP: received packet without ExtIV" 4110ee9f67c4028500a4348e8bc87ee7ec1139b8259Joe Perches " flag from %pM\n", hdr->addr2); 4128fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 4138fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return -2; 4148fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 4158fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang keyidx >>= 6; 4168fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (tkey->key_idx != keyidx) { 4178fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang printk(KERN_DEBUG "TKIP: RX tkey->key_idx=%d frame " 4188fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang "keyidx=%d priv=%p\n", tkey->key_idx, keyidx, priv); 4198fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return -6; 4208fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 4218fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (!tkey->key_set) { 4228fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (net_ratelimit()) { 4230ee9f67c4028500a4348e8bc87ee7ec1139b8259Joe Perches printk(KERN_DEBUG "TKIP: received packet from %pM" 4248fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang " with keyid=%d that does not have a configured" 4250ee9f67c4028500a4348e8bc87ee7ec1139b8259Joe Perches " key\n", hdr->addr2, keyidx); 4268fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 4278fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return -3; 4288fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 4298fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang iv16 = (pos[0] << 8) | pos[2]; 4308fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24); 4318fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang pos += 8; 4328fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 4338fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (!tcb_desc->bHwSec) 4348fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 4358fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (iv32 < tkey->rx_iv32 || 4368fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) { 4378fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (net_ratelimit()) { 4380ee9f67c4028500a4348e8bc87ee7ec1139b8259Joe Perches printk(KERN_DEBUG "TKIP: replay detected: STA=%pM" 4398fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang " previous TSC %08x%04x received TSC " 4400ee9f67c4028500a4348e8bc87ee7ec1139b8259Joe Perches "%08x%04x\n", hdr->addr2, 4418fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->rx_iv32, tkey->rx_iv16, iv32, iv16); 4428fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 4438fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->dot11RSNAStatsTKIPReplays++; 4448fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return -4; 4458fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 4468fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 4478fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (iv32 != tkey->rx_iv32 || !tkey->rx_phase1_done) { 4488fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkip_mixing_phase1(tkey->rx_ttak, tkey->key, hdr->addr2, iv32); 4498fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->rx_phase1_done = 1; 4508fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 4518fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkip_mixing_phase2(rc4key, tkey->key, tkey->rx_ttak, iv16); 4528fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 4538fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang plen = skb->len - hdr_len - 12; 4548fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 4558fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); 4568fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang sg_init_one(&sg, pos, plen+4); 457f61fb9356d20977258bb59a8d9f1857d2c58ac98Mauro Carvalho Chehab 4588fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) { 4598fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (net_ratelimit()) { 4608fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang printk(KERN_DEBUG ": TKIP: failed to decrypt " 4610ee9f67c4028500a4348e8bc87ee7ec1139b8259Joe Perches "received packet from %pM\n", 4620ee9f67c4028500a4348e8bc87ee7ec1139b8259Joe Perches hdr->addr2); 4638fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 4648fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return -7; 4658fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 4668fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 4678fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang crc = ~crc32_le(~0, pos, plen); 4688fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang icv[0] = crc; 4698fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang icv[1] = crc >> 8; 4708fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang icv[2] = crc >> 16; 4718fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang icv[3] = crc >> 24; 4728fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 4738fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (memcmp(icv, pos + plen, 4) != 0) { 4748fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (iv32 != tkey->rx_iv32) { 4758fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* Previously cached Phase1 result was already lost, so 4768fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang * it needs to be recalculated for the next packet. */ 4778fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->rx_phase1_done = 0; 4788fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 4798fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (net_ratelimit()) { 4808fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang printk(KERN_DEBUG "TKIP: ICV error detected: STA=" 4810ee9f67c4028500a4348e8bc87ee7ec1139b8259Joe Perches "%pM\n", hdr->addr2); 4828fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 4838fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->dot11RSNAStatsTKIPICVErrors++; 4848fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return -5; 4858fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 4868fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 4878fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 4888fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 4898fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* Update real counters only after Michael MIC verification has 4908fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang * completed */ 4918fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->rx_iv32_new = iv32; 4928fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->rx_iv16_new = iv16; 4938fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 4948fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* Remove IV and ICV */ 4958fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memmove(skb->data + 8, skb->data, hdr_len); 4968fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang skb_pull(skb, 8); 4978fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang skb_trim(skb, skb->len - 4); 4988fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 4998fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return keyidx; 5008fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 5018fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 5028acfd58a4d53ff3724172e8fbd03c3ac97da5342Xenia Ragiadakoustatic int michael_mic(struct crypto_hash *tfm_michael, u8 *key, u8 *hdr, 5038acfd58a4d53ff3724172e8fbd03c3ac97da5342Xenia Ragiadakou u8 *data, size_t data_len, u8 *mic) 5048fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 505e406322b4b963e622f41d76193d8ca9e5435adb8Mauro Carvalho Chehab struct hash_desc desc; 506e406322b4b963e622f41d76193d8ca9e5435adb8Mauro Carvalho Chehab struct scatterlist sg[2]; 5078fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 508e406322b4b963e622f41d76193d8ca9e5435adb8Mauro Carvalho Chehab if (tfm_michael == NULL) { 509e406322b4b963e622f41d76193d8ca9e5435adb8Mauro Carvalho Chehab printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n"); 510e406322b4b963e622f41d76193d8ca9e5435adb8Mauro Carvalho Chehab return -1; 511e406322b4b963e622f41d76193d8ca9e5435adb8Mauro Carvalho Chehab } 512f61fb9356d20977258bb59a8d9f1857d2c58ac98Mauro Carvalho Chehab 513e406322b4b963e622f41d76193d8ca9e5435adb8Mauro Carvalho Chehab sg_init_table(sg, 2); 514e406322b4b963e622f41d76193d8ca9e5435adb8Mauro Carvalho Chehab sg_set_buf(&sg[0], hdr, 16); 515e406322b4b963e622f41d76193d8ca9e5435adb8Mauro Carvalho Chehab sg_set_buf(&sg[1], data, data_len); 5168fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 517e406322b4b963e622f41d76193d8ca9e5435adb8Mauro Carvalho Chehab if (crypto_hash_setkey(tfm_michael, key, 8)) 518e406322b4b963e622f41d76193d8ca9e5435adb8Mauro Carvalho Chehab return -1; 5198fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 520e406322b4b963e622f41d76193d8ca9e5435adb8Mauro Carvalho Chehab desc.tfm = tfm_michael; 521e406322b4b963e622f41d76193d8ca9e5435adb8Mauro Carvalho Chehab desc.flags = 0; 522e406322b4b963e622f41d76193d8ca9e5435adb8Mauro Carvalho Chehab return crypto_hash_digest(&desc, sg, data_len + 16, mic); 5238fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 5248fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 5258fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangstatic void michael_mic_hdr(struct sk_buff *skb, u8 *hdr) 5268fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 5278fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ieee80211_hdr_4addr *hdr11; 5288fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 5298fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang hdr11 = (struct ieee80211_hdr_4addr *) skb->data; 5308fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang switch (le16_to_cpu(hdr11->frame_ctl) & 5318fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { 5328fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang case IEEE80211_FCTL_TODS: 5338fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */ 5348fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */ 5358fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang break; 5368fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang case IEEE80211_FCTL_FROMDS: 5378fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */ 5388fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memcpy(hdr + ETH_ALEN, hdr11->addr3, ETH_ALEN); /* SA */ 5398fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang break; 5408fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS: 5418fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */ 5428fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */ 5438fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang break; 5448fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang case 0: 5458fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */ 5468fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */ 5478fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang break; 5488fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 5498fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 5508fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang hdr[12] = 0; /* priority */ 5518fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 5528fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */ 5538fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 5548fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 5558fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 5568fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangstatic int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len, void *priv) 5578fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 5588fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ieee80211_tkip_data *tkey = priv; 5598fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u8 *pos; 5608fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ieee80211_hdr_4addr *hdr; 5618fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 5628fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang hdr = (struct ieee80211_hdr_4addr *) skb->data; 5638fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 5648fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (skb_tailroom(skb) < 8 || skb->len < hdr_len) { 5658fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang printk(KERN_DEBUG "Invalid packet for Michael MIC add " 5668fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang "(tailroom=%d hdr_len=%d skb->len=%d)\n", 5678fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang skb_tailroom(skb), hdr_len, skb->len); 5688fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return -1; 5698fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 5708fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 5718fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang michael_mic_hdr(skb, tkey->tx_hdr); 5728fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 5738fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang // { david, 2006.9.1 5748fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang // fix the wpa process with wmm enabled. 5758fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl))) { 5768fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->tx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07; 5778fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 5788fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang // } 5798fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang pos = skb_put(skb, 8); 580f61fb9356d20977258bb59a8d9f1857d2c58ac98Mauro Carvalho Chehab 5818fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr, 5828fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang skb->data + hdr_len, skb->len - 8 - hdr_len, pos)) 5838fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return -1; 5848fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 5858fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return 0; 5868fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 5878fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 5888fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangstatic void ieee80211_michael_mic_failure(struct net_device *dev, 5898fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ieee80211_hdr_4addr *hdr, 5908fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang int keyidx) 5918fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 5928fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang union iwreq_data wrqu; 5938fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct iw_michaelmicfailure ev; 5948fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 5958fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* TODO: needed parameters: count, keyid, key type, TSC */ 5968fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memset(&ev, 0, sizeof(ev)); 5978fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ev.flags = keyidx & IW_MICFAILURE_KEY_ID; 5988fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (hdr->addr1[0] & 0x01) 5998fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ev.flags |= IW_MICFAILURE_GROUP; 6008fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang else 6018fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ev.flags |= IW_MICFAILURE_PAIRWISE; 6028fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ev.src_addr.sa_family = ARPHRD_ETHER; 6038fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memcpy(ev.src_addr.sa_data, hdr->addr2, ETH_ALEN); 6048fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memset(&wrqu, 0, sizeof(wrqu)); 6058fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang wrqu.data.length = sizeof(ev); 6068fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *) &ev); 6078fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 6088fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6098fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangstatic int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx, 6108fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang int hdr_len, void *priv) 6118fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 6128fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ieee80211_tkip_data *tkey = priv; 6138fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u8 mic[8]; 6148fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ieee80211_hdr_4addr *hdr; 6158fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6168fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang hdr = (struct ieee80211_hdr_4addr *) skb->data; 6178fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6188fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (!tkey->key_set) 6198fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return -1; 6208fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6218fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang michael_mic_hdr(skb, tkey->rx_hdr); 6228fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang // { david, 2006.9.1 6238fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang // fix the wpa process with wmm enabled. 6248fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl))) { 6258fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->rx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07; 6268fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 6278fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang // } 6288fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6298fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr, 6308fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang skb->data + hdr_len, skb->len - 8 - hdr_len, mic)) 631e406322b4b963e622f41d76193d8ca9e5435adb8Mauro Carvalho Chehab return -1; 6328fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) { 6338fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ieee80211_hdr_4addr *hdr; 6348fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang hdr = (struct ieee80211_hdr_4addr *) skb->data; 6358fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang printk(KERN_DEBUG "%s: Michael MIC verification failed for " 6360ee9f67c4028500a4348e8bc87ee7ec1139b8259Joe Perches "MSDU from %pM keyidx=%d\n", 6370ee9f67c4028500a4348e8bc87ee7ec1139b8259Joe Perches skb->dev ? skb->dev->name : "N/A", hdr->addr2, 6388fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang keyidx); 6398fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (skb->dev) 6408fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ieee80211_michael_mic_failure(skb->dev, hdr, keyidx); 6418fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->dot11RSNAStatsTKIPLocalMICFailures++; 6428fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return -1; 6438fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 6448fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6458fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* Update TSC counters for RX now that the packet verification has 6468fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang * completed. */ 6478fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->rx_iv32 = tkey->rx_iv32_new; 6488fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->rx_iv16 = tkey->rx_iv16_new; 6498fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6508fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang skb_trim(skb, skb->len - 8); 6518fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6528fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return 0; 6538fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 6548fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6558fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6568fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangstatic int ieee80211_tkip_set_key(void *key, int len, u8 *seq, void *priv) 6578fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 6588fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ieee80211_tkip_data *tkey = priv; 6598fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang int keyidx; 6608fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct crypto_hash *tfm = tkey->tx_tfm_michael; 6618fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4; 6628fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct crypto_hash *tfm3 = tkey->rx_tfm_michael; 6638fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct crypto_blkcipher *tfm4 = tkey->rx_tfm_arc4; 6648fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6658fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang keyidx = tkey->key_idx; 6668fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memset(tkey, 0, sizeof(*tkey)); 6678fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->key_idx = keyidx; 6688fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->tx_tfm_michael = tfm; 6698fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->tx_tfm_arc4 = tfm2; 6708fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->rx_tfm_michael = tfm3; 6718fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->rx_tfm_arc4 = tfm4; 6728fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6738fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (len == TKIP_KEY_LEN) { 6748fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memcpy(tkey->key, key, TKIP_KEY_LEN); 6758fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->key_set = 1; 6768fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->tx_iv16 = 1; /* TSC is initialized to 1 */ 6778fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (seq) { 6788fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->rx_iv32 = (seq[5] << 24) | (seq[4] << 16) | 6798fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang (seq[3] << 8) | seq[2]; 6808fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->rx_iv16 = (seq[1] << 8) | seq[0]; 6818fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 6828fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } else if (len == 0) 6838fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkey->key_set = 0; 6848fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang else 6858fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return -1; 6868fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6878fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return 0; 6888fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 6898fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6908fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6918fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangstatic int ieee80211_tkip_get_key(void *key, int len, u8 *seq, void *priv) 6928fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 6938fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ieee80211_tkip_data *tkey = priv; 6948fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6958fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (len < TKIP_KEY_LEN) 6968fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return -1; 6978fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6988fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (!tkey->key_set) 6998fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return 0; 7008fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memcpy(key, tkey->key, TKIP_KEY_LEN); 7018fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 7028fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (seq) { 7038fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* Return the sequence number of the last transmitted frame. */ 7048fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u16 iv16 = tkey->tx_iv16; 7058fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u32 iv32 = tkey->tx_iv32; 7068fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (iv16 == 0) 7078fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang iv32--; 7088fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang iv16--; 7098fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang seq[0] = tkey->tx_iv16; 7108fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang seq[1] = tkey->tx_iv16 >> 8; 7118fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang seq[2] = tkey->tx_iv32; 7128fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang seq[3] = tkey->tx_iv32 >> 8; 7138fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang seq[4] = tkey->tx_iv32 >> 16; 7148fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang seq[5] = tkey->tx_iv32 >> 24; 7158fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 7168fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 7178fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return TKIP_KEY_LEN; 7188fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 7198fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 7208fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 7218acfd58a4d53ff3724172e8fbd03c3ac97da5342Xenia Ragiadakoustatic char *ieee80211_tkip_print_stats(char *p, void *priv) 7228fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 7238fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ieee80211_tkip_data *tkip = priv; 7248fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang p += sprintf(p, "key[%d] alg=TKIP key_set=%d " 7258fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang "tx_pn=%02x%02x%02x%02x%02x%02x " 7268fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang "rx_pn=%02x%02x%02x%02x%02x%02x " 7278fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang "replays=%d icv_errors=%d local_mic_failures=%d\n", 7288fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkip->key_idx, tkip->key_set, 7298fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang (tkip->tx_iv32 >> 24) & 0xff, 7308fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang (tkip->tx_iv32 >> 16) & 0xff, 7318fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang (tkip->tx_iv32 >> 8) & 0xff, 7328fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkip->tx_iv32 & 0xff, 7338fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang (tkip->tx_iv16 >> 8) & 0xff, 7348fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkip->tx_iv16 & 0xff, 7358fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang (tkip->rx_iv32 >> 24) & 0xff, 7368fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang (tkip->rx_iv32 >> 16) & 0xff, 7378fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang (tkip->rx_iv32 >> 8) & 0xff, 7388fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkip->rx_iv32 & 0xff, 7398fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang (tkip->rx_iv16 >> 8) & 0xff, 7408fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkip->rx_iv16 & 0xff, 7418fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkip->dot11RSNAStatsTKIPReplays, 7428fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkip->dot11RSNAStatsTKIPICVErrors, 7438fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tkip->dot11RSNAStatsTKIPLocalMICFailures); 7448fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return p; 7458fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 7468fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 7478fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 7488fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangstatic struct ieee80211_crypto_ops ieee80211_crypt_tkip = { 7498fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang .name = "TKIP", 7508fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang .init = ieee80211_tkip_init, 7518fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang .deinit = ieee80211_tkip_deinit, 7528fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang .encrypt_mpdu = ieee80211_tkip_encrypt, 7538fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang .decrypt_mpdu = ieee80211_tkip_decrypt, 7548fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang .encrypt_msdu = ieee80211_michael_mic_add, 7558fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang .decrypt_msdu = ieee80211_michael_mic_verify, 7568fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang .set_key = ieee80211_tkip_set_key, 7578fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang .get_key = ieee80211_tkip_get_key, 7588fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang .print_stats = ieee80211_tkip_print_stats, 7598fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang .extra_prefix_len = 4 + 4, /* IV + ExtIV */ 7608fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang .extra_postfix_len = 8 + 4, /* MIC + ICV */ 761e406322b4b963e622f41d76193d8ca9e5435adb8Mauro Carvalho Chehab .owner = THIS_MODULE, 7628fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang}; 7638fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 764f61fb9356d20977258bb59a8d9f1857d2c58ac98Mauro Carvalho Chehabint __init ieee80211_crypto_tkip_init(void) 7658fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 7668fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return ieee80211_register_crypto_ops(&ieee80211_crypt_tkip); 7678fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 7688fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 769f61fb9356d20977258bb59a8d9f1857d2c58ac98Mauro Carvalho Chehabvoid __exit ieee80211_crypto_tkip_exit(void) 7708fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 7718fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ieee80211_unregister_crypto_ops(&ieee80211_crypt_tkip); 7728fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 7738fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 7748fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangvoid ieee80211_tkip_null(void) 7758fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 776f8628a47ba502ec2ec795dc0134f052f45ce2cd4Joe Perches// printk("============>%s()\n", __func__); 777e406322b4b963e622f41d76193d8ca9e5435adb8Mauro Carvalho Chehab return; 7788fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 779