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