aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/hostap
diff options
context:
space:
mode:
authorJouni Malinen <jkmaline@cc.hut.fi>2005-07-30 23:43:20 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-07-31 00:28:02 -0400
commit62fe7e378109537ff80971c5208e12d40bf88bee (patch)
tree6facd4654afbef6590e21c4fde0c71fb7ed79f2e /drivers/net/wireless/hostap
parentebed67d2847a9d299b47eeb5d82744671ab2b198 (diff)
[PATCH] hostap: Replace crypto code with net/ieee80211 version
Replace Host AP version of WEP, TKIP, CCMP implementation with net/ieee80211 that has more or less identical implementation (since it is based on the Host AP implementation). Remove Host AP specific implementation and modules from drivers/net/wireless/hostap. Signed-off-by: Jouni Malinen <jkmaline@cc.hut.fi> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers/net/wireless/hostap')
-rw-r--r--drivers/net/wireless/hostap/Kconfig33
-rw-r--r--drivers/net/wireless/hostap/Makefile3
-rw-r--r--drivers/net/wireless/hostap/hostap.c12
-rw-r--r--drivers/net/wireless/hostap/hostap_80211.h2
-rw-r--r--drivers/net/wireless/hostap/hostap_80211_rx.c6
-rw-r--r--drivers/net/wireless/hostap/hostap_80211_tx.c2
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.c13
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.h9
-rw-r--r--drivers/net/wireless/hostap/hostap_crypt.c167
-rw-r--r--drivers/net/wireless/hostap/hostap_crypt.h50
-rw-r--r--drivers/net/wireless/hostap/hostap_crypt_ccmp.c487
-rw-r--r--drivers/net/wireless/hostap/hostap_crypt_tkip.c697
-rw-r--r--drivers/net/wireless/hostap/hostap_crypt_wep.c283
-rw-r--r--drivers/net/wireless/hostap/hostap_hw.c8
-rw-r--r--drivers/net/wireless/hostap/hostap_ioctl.c77
-rw-r--r--drivers/net/wireless/hostap/hostap_wlan.h10
16 files changed, 64 insertions, 1795 deletions
diff --git a/drivers/net/wireless/hostap/Kconfig b/drivers/net/wireless/hostap/Kconfig
index 2871e879b518..1445f3f2600f 100644
--- a/drivers/net/wireless/hostap/Kconfig
+++ b/drivers/net/wireless/hostap/Kconfig
@@ -7,9 +7,6 @@ config HOSTAP
7 Host AP mode that allows the card to act as an IEEE 802.11 7 Host AP mode that allows the card to act as an IEEE 802.11
8 access point. 8 access point.
9 9
10 In addition, this includes generic IEEE 802.11 code, e.g., for
11 WEP/TKIP/CCMP encryption that can be shared with other drivers.
12
13 See <http://hostap.epitest.fi/> for more information about the 10 See <http://hostap.epitest.fi/> for more information about the
14 Host AP driver configuration and tools. This site includes 11 Host AP driver configuration and tools. This site includes
15 information and tools (hostapd and wpa_supplicant) for WPA/WPA2 12 information and tools (hostapd and wpa_supplicant) for WPA/WPA2
@@ -22,36 +19,6 @@ config HOSTAP
22 The driver can be compiled as a module and it will be called 19 The driver can be compiled as a module and it will be called
23 "hostap.ko". 20 "hostap.ko".
24 21
25config HOSTAP_WEP
26 tristate "IEEE 802.11 WEP encryption"
27 depends on HOSTAP
28 select CRYPTO
29 ---help---
30 Software implementation of IEEE 802.11 WEP encryption.
31
32 This can be compiled as a modules and it will be called
33 "hostap_crypt_wep.ko".
34
35config HOSTAP_TKIP
36 tristate "IEEE 802.11 TKIP encryption"
37 depends on HOSTAP
38 select CRYPTO
39 ---help---
40 Software implementation of IEEE 802.11 TKIP encryption.
41
42 This can be compiled as a modules and it will be called
43 "hostap_crypt_tkip.ko".
44
45config HOSTAP_CCMP
46 tristate "IEEE 802.11 CCMP encryption"
47 depends on HOSTAP
48 select CRYPTO
49 ---help---
50 Software implementation of IEEE 802.11 CCMP encryption.
51
52 This can be compiled as a modules and it will be called
53 "hostap_crypt_ccmp.ko".
54
55config HOSTAP_FIRMWARE 22config HOSTAP_FIRMWARE
56 bool "Support downloading firmware images with Host AP driver" 23 bool "Support downloading firmware images with Host AP driver"
57 depends on HOSTAP 24 depends on HOSTAP
diff --git a/drivers/net/wireless/hostap/Makefile b/drivers/net/wireless/hostap/Makefile
index 087554075038..fc62235bfc24 100644
--- a/drivers/net/wireless/hostap/Makefile
+++ b/drivers/net/wireless/hostap/Makefile
@@ -1,7 +1,4 @@
1obj-$(CONFIG_HOSTAP) += hostap.o 1obj-$(CONFIG_HOSTAP) += hostap.o
2obj-$(CONFIG_HOSTAP_WEP) += hostap_crypt_wep.o
3obj-$(CONFIG_HOSTAP_TKIP) += hostap_crypt_tkip.o
4obj-$(CONFIG_HOSTAP_CCMP) += hostap_crypt_ccmp.o
5 2
6obj-$(CONFIG_HOSTAP_CS) += hostap_cs.o 3obj-$(CONFIG_HOSTAP_CS) += hostap_cs.o
7obj-$(CONFIG_HOSTAP_PLX) += hostap_plx.o 4obj-$(CONFIG_HOSTAP_PLX) += hostap_plx.o
diff --git a/drivers/net/wireless/hostap/hostap.c b/drivers/net/wireless/hostap/hostap.c
index 75c75103f678..0858eba4575f 100644
--- a/drivers/net/wireless/hostap/hostap.c
+++ b/drivers/net/wireless/hostap/hostap.c
@@ -4,7 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen 5 * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
6 * <jkmaline@cc.hut.fi> 6 * <jkmaline@cc.hut.fi>
7 * Copyright (c) 2002-2004, Jouni Malinen <jkmaline@cc.hut.fi> 7 * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi>
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as 10 * it under the terms of the GNU General Public License version 2 as
@@ -34,16 +34,12 @@
34#include "hostap_80211.h" 34#include "hostap_80211.h"
35#include "hostap_ap.h" 35#include "hostap_ap.h"
36#include "hostap.h" 36#include "hostap.h"
37#include "hostap_crypt.h"
38 37
39MODULE_AUTHOR("Jouni Malinen"); 38MODULE_AUTHOR("Jouni Malinen");
40MODULE_DESCRIPTION("Host AP common routines"); 39MODULE_DESCRIPTION("Host AP common routines");
41MODULE_LICENSE("GPL"); 40MODULE_LICENSE("GPL");
42MODULE_VERSION(PRISM2_VERSION); 41MODULE_VERSION(PRISM2_VERSION);
43 42
44/* Old hostap_crypt module is now part of hostap module. */
45#include "hostap_crypt.c"
46
47#define TX_TIMEOUT (2 * HZ) 43#define TX_TIMEOUT (2 * HZ)
48 44
49#define PRISM2_MAX_FRAME_SIZE 2304 45#define PRISM2_MAX_FRAME_SIZE 2304
@@ -66,7 +62,7 @@ static int prism2_ap_translate_scan(struct net_device *dev, char *buffer);
66static int prism2_hostapd(struct ap_data *ap, 62static int prism2_hostapd(struct ap_data *ap,
67 struct prism2_hostapd_param *param); 63 struct prism2_hostapd_param *param);
68static void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent, 64static void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
69 struct prism2_crypt_data ***crypt); 65 struct ieee80211_crypt_data ***crypt);
70static void ap_control_kickall(struct ap_data *ap); 66static void ap_control_kickall(struct ap_data *ap);
71#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT 67#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
72static int ap_control_add_mac(struct mac_restrictions *mac_restrictions, 68static int ap_control_add_mac(struct mac_restrictions *mac_restrictions,
@@ -1156,8 +1152,6 @@ struct proc_dir_entry *hostap_proc;
1156 1152
1157static int __init hostap_init(void) 1153static int __init hostap_init(void)
1158{ 1154{
1159 hostap_crypto_init();
1160
1161 if (proc_net != NULL) { 1155 if (proc_net != NULL) {
1162 hostap_proc = proc_mkdir("hostap", proc_net); 1156 hostap_proc = proc_mkdir("hostap", proc_net);
1163 if (!hostap_proc) 1157 if (!hostap_proc)
@@ -1176,8 +1170,6 @@ static void __exit hostap_exit(void)
1176 hostap_proc = NULL; 1170 hostap_proc = NULL;
1177 remove_proc_entry("hostap", proc_net); 1171 remove_proc_entry("hostap", proc_net);
1178 } 1172 }
1179
1180 hostap_crypto_deinit();
1181} 1173}
1182 1174
1183 1175
diff --git a/drivers/net/wireless/hostap/hostap_80211.h b/drivers/net/wireless/hostap/hostap_80211.h
index 878151f40657..f3ad3445c72e 100644
--- a/drivers/net/wireless/hostap/hostap_80211.h
+++ b/drivers/net/wireless/hostap/hostap_80211.h
@@ -101,7 +101,7 @@ void hostap_dump_tx_80211(const char *name, struct sk_buff *skb);
101int hostap_data_start_xmit(struct sk_buff *skb, struct net_device *dev); 101int hostap_data_start_xmit(struct sk_buff *skb, struct net_device *dev);
102int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev); 102int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev);
103struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb, 103struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
104 struct prism2_crypt_data *crypt); 104 struct ieee80211_crypt_data *crypt);
105int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev); 105int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev);
106 106
107#endif /* HOSTAP_80211_H */ 107#endif /* HOSTAP_80211_H */
diff --git a/drivers/net/wireless/hostap/hostap_80211_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c
index a0da9b9c890c..f4ca1e88f314 100644
--- a/drivers/net/wireless/hostap/hostap_80211_rx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_rx.c
@@ -613,7 +613,7 @@ static int hostap_is_eapol_frame(local_info_t *local, struct sk_buff *skb)
613/* Called only as a tasklet (software IRQ) */ 613/* Called only as a tasklet (software IRQ) */
614static inline int 614static inline int
615hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb, 615hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
616 struct prism2_crypt_data *crypt) 616 struct ieee80211_crypt_data *crypt)
617{ 617{
618 struct hostap_ieee80211_hdr *hdr; 618 struct hostap_ieee80211_hdr *hdr;
619 int res, hdrlen; 619 int res, hdrlen;
@@ -652,7 +652,7 @@ hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
652/* Called only as a tasklet (software IRQ) */ 652/* Called only as a tasklet (software IRQ) */
653static inline int 653static inline int
654hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb, 654hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb,
655 int keyidx, struct prism2_crypt_data *crypt) 655 int keyidx, struct ieee80211_crypt_data *crypt)
656{ 656{
657 struct hostap_ieee80211_hdr *hdr; 657 struct hostap_ieee80211_hdr *hdr;
658 int res, hdrlen; 658 int res, hdrlen;
@@ -698,7 +698,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
698 int from_assoc_ap = 0; 698 int from_assoc_ap = 0;
699 u8 dst[ETH_ALEN]; 699 u8 dst[ETH_ALEN];
700 u8 src[ETH_ALEN]; 700 u8 src[ETH_ALEN];
701 struct prism2_crypt_data *crypt = NULL; 701 struct ieee80211_crypt_data *crypt = NULL;
702 void *sta = NULL; 702 void *sta = NULL;
703 int keyidx = 0; 703 int keyidx = 0;
704 704
diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c
index 52e81cd406fb..8f39871d6908 100644
--- a/drivers/net/wireless/hostap/hostap_80211_tx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_tx.c
@@ -284,7 +284,7 @@ int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev)
284 284
285/* Called only from software IRQ */ 285/* Called only from software IRQ */
286struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb, 286struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
287 struct prism2_crypt_data *crypt) 287 struct ieee80211_crypt_data *crypt)
288{ 288{
289 struct hostap_interface *iface; 289 struct hostap_interface *iface;
290 local_info_t *local; 290 local_info_t *local;
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index f59912a0fb4c..6e109dfb43e7 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -2,7 +2,7 @@
2 * Intersil Prism2 driver with Host AP (software access point) support 2 * Intersil Prism2 driver with Host AP (software access point) support
3 * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen 3 * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
4 * <jkmaline@cc.hut.fi> 4 * <jkmaline@cc.hut.fi>
5 * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi> 5 * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi>
6 * 6 *
7 * This file is to be included into hostap.c when S/W AP functionality is 7 * This file is to be included into hostap.c when S/W AP functionality is
8 * compiled. 8 * compiled.
@@ -1206,7 +1206,7 @@ static void prism2_check_tx_rates(struct sta_info *sta)
1206 1206
1207static void ap_crypt_init(struct ap_data *ap) 1207static void ap_crypt_init(struct ap_data *ap)
1208{ 1208{
1209 ap->crypt = hostap_get_crypto_ops("WEP"); 1209 ap->crypt = ieee80211_get_crypto_ops("WEP");
1210 1210
1211 if (ap->crypt) { 1211 if (ap->crypt) {
1212 if (ap->crypt->init) { 1212 if (ap->crypt->init) {
@@ -1224,7 +1224,7 @@ static void ap_crypt_init(struct ap_data *ap)
1224 1224
1225 if (ap->crypt == NULL) { 1225 if (ap->crypt == NULL) {
1226 printk(KERN_WARNING "AP could not initialize WEP: load module " 1226 printk(KERN_WARNING "AP could not initialize WEP: load module "
1227 "hostap_crypt_wep.o\n"); 1227 "ieee80211_crypt_wep.ko\n");
1228 } 1228 }
1229} 1229}
1230 1230
@@ -1293,7 +1293,7 @@ static void handle_authen(local_info_t *local, struct sk_buff *skb,
1293 u16 auth_alg, auth_transaction, status_code, *pos; 1293 u16 auth_alg, auth_transaction, status_code, *pos;
1294 u16 resp = WLAN_STATUS_SUCCESS, fc; 1294 u16 resp = WLAN_STATUS_SUCCESS, fc;
1295 struct sta_info *sta = NULL; 1295 struct sta_info *sta = NULL;
1296 struct prism2_crypt_data *crypt; 1296 struct ieee80211_crypt_data *crypt;
1297 char *txt = ""; 1297 char *txt = "";
1298 1298
1299 len = skb->len - IEEE80211_MGMT_HDR_LEN; 1299 len = skb->len - IEEE80211_MGMT_HDR_LEN;
@@ -3058,7 +3058,8 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
3058/* Called only as a tasklet (software IRQ) */ 3058/* Called only as a tasklet (software IRQ) */
3059int hostap_handle_sta_crypto(local_info_t *local, 3059int hostap_handle_sta_crypto(local_info_t *local,
3060 struct hostap_ieee80211_hdr *hdr, 3060 struct hostap_ieee80211_hdr *hdr,
3061 struct prism2_crypt_data **crypt, void **sta_ptr) 3061 struct ieee80211_crypt_data **crypt,
3062 void **sta_ptr)
3062{ 3063{
3063 struct sta_info *sta; 3064 struct sta_info *sta;
3064 3065
@@ -3206,7 +3207,7 @@ void hostap_update_rates(local_info_t *local)
3206 3207
3207 3208
3208static void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent, 3209static void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
3209 struct prism2_crypt_data ***crypt) 3210 struct ieee80211_crypt_data ***crypt)
3210{ 3211{
3211 struct sta_info *sta; 3212 struct sta_info *sta;
3212 3213
diff --git a/drivers/net/wireless/hostap/hostap_ap.h b/drivers/net/wireless/hostap/hostap_ap.h
index 10137f44436d..137f78e4532b 100644
--- a/drivers/net/wireless/hostap/hostap_ap.h
+++ b/drivers/net/wireless/hostap/hostap_ap.h
@@ -81,7 +81,7 @@ struct sta_info {
81 u32 tx_since_last_failure; 81 u32 tx_since_last_failure;
82 u32 tx_consecutive_exc; 82 u32 tx_consecutive_exc;
83 83
84 struct prism2_crypt_data *crypt; 84 struct ieee80211_crypt_data *crypt;
85 85
86 int ap; /* whether this station is an AP */ 86 int ap; /* whether this station is an AP */
87 87
@@ -216,7 +216,7 @@ struct ap_data {
216 216
217 /* WEP operations for generating challenges to be used with shared key 217 /* WEP operations for generating challenges to be used with shared key
218 * authentication */ 218 * authentication */
219 struct hostap_crypto_ops *crypt; 219 struct ieee80211_crypto_ops *crypt;
220 void *crypt_priv; 220 void *crypt_priv;
221#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ 221#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
222}; 222};
@@ -236,7 +236,7 @@ typedef enum {
236struct hostap_tx_data { 236struct hostap_tx_data {
237 struct sk_buff *skb; 237 struct sk_buff *skb;
238 int host_encrypt; 238 int host_encrypt;
239 struct prism2_crypt_data *crypt; 239 struct ieee80211_crypt_data *crypt;
240 void *sta_ptr; 240 void *sta_ptr;
241}; 241};
242ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx); 242ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx);
@@ -253,7 +253,8 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
253 int wds); 253 int wds);
254int hostap_handle_sta_crypto(local_info_t *local, 254int hostap_handle_sta_crypto(local_info_t *local,
255 struct hostap_ieee80211_hdr *hdr, 255 struct hostap_ieee80211_hdr *hdr,
256 struct prism2_crypt_data **crypt, void **sta_ptr); 256 struct ieee80211_crypt_data **crypt,
257 void **sta_ptr);
257int hostap_is_sta_assoc(struct ap_data *ap, u8 *sta_addr); 258int hostap_is_sta_assoc(struct ap_data *ap, u8 *sta_addr);
258int hostap_is_sta_authorized(struct ap_data *ap, u8 *sta_addr); 259int hostap_is_sta_authorized(struct ap_data *ap, u8 *sta_addr);
259int hostap_add_sta(struct ap_data *ap, u8 *sta_addr); 260int hostap_add_sta(struct ap_data *ap, u8 *sta_addr);
diff --git a/drivers/net/wireless/hostap/hostap_crypt.c b/drivers/net/wireless/hostap/hostap_crypt.c
deleted file mode 100644
index de5390d502f1..000000000000
--- a/drivers/net/wireless/hostap/hostap_crypt.c
+++ /dev/null
@@ -1,167 +0,0 @@
1/*
2 * Host AP crypto routines
3 *
4 * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation. See README and COPYING for
9 * more details.
10 */
11
12struct hostap_crypto_alg {
13 struct list_head list;
14 struct hostap_crypto_ops *ops;
15};
16
17
18struct hostap_crypto {
19 struct list_head algs;
20 spinlock_t lock;
21};
22
23static struct hostap_crypto *hcrypt;
24
25
26int hostap_register_crypto_ops(struct hostap_crypto_ops *ops)
27{
28 unsigned long flags;
29 struct hostap_crypto_alg *alg;
30
31 if (hcrypt == NULL)
32 return -1;
33
34 alg = (struct hostap_crypto_alg *) kmalloc(sizeof(*alg), GFP_KERNEL);
35 if (alg == NULL)
36 return -ENOMEM;
37
38 memset(alg, 0, sizeof(*alg));
39 alg->ops = ops;
40
41 spin_lock_irqsave(&hcrypt->lock, flags);
42 list_add(&alg->list, &hcrypt->algs);
43 spin_unlock_irqrestore(&hcrypt->lock, flags);
44
45 printk(KERN_DEBUG "hostap_crypt: registered algorithm '%s'\n",
46 ops->name);
47
48 return 0;
49}
50
51
52int hostap_unregister_crypto_ops(struct hostap_crypto_ops *ops)
53{
54 unsigned long flags;
55 struct list_head *ptr;
56 struct hostap_crypto_alg *del_alg = NULL;
57
58 if (hcrypt == NULL)
59 return -1;
60
61 spin_lock_irqsave(&hcrypt->lock, flags);
62 for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
63 struct hostap_crypto_alg *alg =
64 (struct hostap_crypto_alg *) ptr;
65 if (alg->ops == ops) {
66 list_del(&alg->list);
67 del_alg = alg;
68 break;
69 }
70 }
71 spin_unlock_irqrestore(&hcrypt->lock, flags);
72
73 if (del_alg) {
74 printk(KERN_DEBUG "hostap_crypt: unregistered algorithm "
75 "'%s'\n", ops->name);
76 kfree(del_alg);
77 }
78
79 return del_alg ? 0 : -1;
80}
81
82
83struct hostap_crypto_ops * hostap_get_crypto_ops(const char *name)
84{
85 unsigned long flags;
86 struct list_head *ptr;
87 struct hostap_crypto_alg *found_alg = NULL;
88
89 if (hcrypt == NULL)
90 return NULL;
91
92 spin_lock_irqsave(&hcrypt->lock, flags);
93 for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
94 struct hostap_crypto_alg *alg =
95 (struct hostap_crypto_alg *) ptr;
96 if (strcmp(alg->ops->name, name) == 0) {
97 found_alg = alg;
98 break;
99 }
100 }
101 spin_unlock_irqrestore(&hcrypt->lock, flags);
102
103 if (found_alg)
104 return found_alg->ops;
105 else
106 return NULL;
107}
108
109
110static void * hostap_crypt_null_init(int keyidx) { return (void *) 1; }
111static void hostap_crypt_null_deinit(void *priv) {}
112
113static struct hostap_crypto_ops hostap_crypt_null = {
114 .name = "NULL",
115 .init = hostap_crypt_null_init,
116 .deinit = hostap_crypt_null_deinit,
117 .encrypt_mpdu = NULL,
118 .decrypt_mpdu = NULL,
119 .encrypt_msdu = NULL,
120 .decrypt_msdu = NULL,
121 .set_key = NULL,
122 .get_key = NULL,
123 .extra_prefix_len = 0,
124 .extra_postfix_len = 0
125};
126
127
128static int __init hostap_crypto_init(void)
129{
130 hcrypt = (struct hostap_crypto *) kmalloc(sizeof(*hcrypt), GFP_KERNEL);
131 if (hcrypt == NULL)
132 return -ENOMEM;
133
134 memset(hcrypt, 0, sizeof(*hcrypt));
135 INIT_LIST_HEAD(&hcrypt->algs);
136 spin_lock_init(&hcrypt->lock);
137
138 (void) hostap_register_crypto_ops(&hostap_crypt_null);
139
140 return 0;
141}
142
143
144static void __exit hostap_crypto_deinit(void)
145{
146 struct list_head *ptr, *n;
147
148 if (hcrypt == NULL)
149 return;
150
151 for (ptr = hcrypt->algs.next, n = ptr->next; ptr != &hcrypt->algs;
152 ptr = n, n = ptr->next) {
153 struct hostap_crypto_alg *alg =
154 (struct hostap_crypto_alg *) ptr;
155 list_del(ptr);
156 printk(KERN_DEBUG "hostap_crypt: unregistered algorithm "
157 "'%s' (deinit)\n", alg->ops->name);
158 kfree(alg);
159 }
160
161 kfree(hcrypt);
162}
163
164
165EXPORT_SYMBOL(hostap_register_crypto_ops);
166EXPORT_SYMBOL(hostap_unregister_crypto_ops);
167EXPORT_SYMBOL(hostap_get_crypto_ops);
diff --git a/drivers/net/wireless/hostap/hostap_crypt.h b/drivers/net/wireless/hostap/hostap_crypt.h
deleted file mode 100644
index 45d66d0323b0..000000000000
--- a/drivers/net/wireless/hostap/hostap_crypt.h
+++ /dev/null
@@ -1,50 +0,0 @@
1#ifndef PRISM2_CRYPT_H
2#define PRISM2_CRYPT_H
3
4struct hostap_crypto_ops {
5 char *name;
6
7 /* init new crypto context (e.g., allocate private data space,
8 * select IV, etc.); returns NULL on failure or pointer to allocated
9 * private data on success */
10 void * (*init)(int keyidx);
11
12 /* deinitialize crypto context and free allocated private data */
13 void (*deinit)(void *priv);
14
15 /* encrypt/decrypt return < 0 on error or >= 0 on success. The return
16 * value from decrypt_mpdu is passed as the keyidx value for
17 * decrypt_msdu. skb must have enough head and tail room for the
18 * encryption; if not, error will be returned; these functions are
19 * called for all MPDUs (i.e., fragments).
20 */
21 int (*encrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
22 int (*decrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
23
24 /* These functions are called for full MSDUs, i.e. full frames.
25 * These can be NULL if full MSDU operations are not needed. */
26 int (*encrypt_msdu)(struct sk_buff *skb, int hdr_len, void *priv);
27 int (*decrypt_msdu)(struct sk_buff *skb, int keyidx, int hdr_len,
28 void *priv);
29
30 int (*set_key)(void *key, int len, u8 *seq, void *priv);
31 int (*get_key)(void *key, int len, u8 *seq, void *priv);
32
33 /* procfs handler for printing out key information and possible
34 * statistics */
35 char * (*print_stats)(char *p, void *priv);
36
37 /* maximum number of bytes added by encryption; encrypt buf is
38 * allocated with extra_prefix_len bytes, copy of in_buf, and
39 * extra_postfix_len; encrypt need not use all this space, but
40 * the result must start at the beginning of the buffer and correct
41 * length must be returned */
42 int extra_prefix_len, extra_postfix_len;
43};
44
45
46int hostap_register_crypto_ops(struct hostap_crypto_ops *ops);
47int hostap_unregister_crypto_ops(struct hostap_crypto_ops *ops);
48struct hostap_crypto_ops * hostap_get_crypto_ops(const char *name);
49
50#endif /* PRISM2_CRYPT_H */
diff --git a/drivers/net/wireless/hostap/hostap_crypt_ccmp.c b/drivers/net/wireless/hostap/hostap_crypt_ccmp.c
deleted file mode 100644
index 9e18340f7a38..000000000000
--- a/drivers/net/wireless/hostap/hostap_crypt_ccmp.c
+++ /dev/null
@@ -1,487 +0,0 @@
1/*
2 * Host AP crypt: host-based CCMP encryption implementation for Host AP driver
3 *
4 * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation. See README and COPYING for
9 * more details.
10 */
11
12#include <linux/config.h>
13#include <linux/version.h>
14#include <linux/module.h>
15#include <linux/init.h>
16#include <linux/slab.h>
17#include <linux/random.h>
18#include <linux/skbuff.h>
19#include <linux/netdevice.h>
20#include <linux/if_ether.h>
21#include <linux/if_arp.h>
22#include <linux/wireless.h>
23#include <net/iw_handler.h>
24#include <asm/string.h>
25
26#include "hostap_crypt.h"
27#include "hostap_wlan.h"
28#include "hostap_80211.h"
29
30#ifndef CONFIG_CRYPTO
31#error CONFIG_CRYPTO is required to build this module.
32#endif
33#include <linux/crypto.h>
34#include <asm/scatterlist.h>
35
36MODULE_AUTHOR("Jouni Malinen");
37MODULE_DESCRIPTION("Host AP crypt: CCMP");
38MODULE_LICENSE("GPL");
39MODULE_VERSION(PRISM2_VERSION);
40
41
42#define AES_BLOCK_LEN 16
43#define CCMP_HDR_LEN 8
44#define CCMP_MIC_LEN 8
45#define CCMP_TK_LEN 16
46#define CCMP_PN_LEN 6
47
48
49struct hostap_ccmp_data {
50 u8 key[CCMP_TK_LEN];
51 int key_set;
52
53 u8 tx_pn[CCMP_PN_LEN];
54 u8 rx_pn[CCMP_PN_LEN];
55
56 u32 dot11RSNAStatsCCMPFormatErrors;
57 u32 dot11RSNAStatsCCMPReplays;
58 u32 dot11RSNAStatsCCMPDecryptErrors;
59
60 int key_idx;
61
62 struct crypto_tfm *tfm;
63
64 /* scratch buffers for virt_to_page() (crypto API) */
65 u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN],
66 tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN];
67 u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN];
68};
69
70
71void hostap_ccmp_aes_encrypt(struct crypto_tfm *tfm,
72 const u8 pt[16], u8 ct[16])
73{
74 struct scatterlist src, dst;
75
76 src.page = virt_to_page(pt);
77 src.offset = offset_in_page(pt);
78 src.length = AES_BLOCK_LEN;
79
80 dst.page = virt_to_page(ct);
81 dst.offset = offset_in_page(ct);
82 dst.length = AES_BLOCK_LEN;
83
84 crypto_cipher_encrypt(tfm, &dst, &src, AES_BLOCK_LEN);
85}
86
87
88static void * hostap_ccmp_init(int key_idx)
89{
90 struct hostap_ccmp_data *priv;
91
92 if (!try_module_get(THIS_MODULE))
93 return NULL;
94
95 priv = (struct hostap_ccmp_data *) kmalloc(sizeof(*priv), GFP_ATOMIC);
96 if (priv == NULL) {
97 goto fail;
98 }
99 memset(priv, 0, sizeof(*priv));
100 priv->key_idx = key_idx;
101
102 priv->tfm = crypto_alloc_tfm("aes", 0);
103 if (priv->tfm == NULL) {
104 printk(KERN_DEBUG "hostap_crypt_ccmp: could not allocate "
105 "crypto API aes\n");
106 goto fail;
107 }
108
109 return priv;
110
111fail:
112 if (priv) {
113 if (priv->tfm)
114 crypto_free_tfm(priv->tfm);
115 kfree(priv);
116 }
117 module_put(THIS_MODULE);
118 return NULL;
119}
120
121
122static void hostap_ccmp_deinit(void *priv)
123{
124 struct hostap_ccmp_data *_priv = priv;
125 if (_priv && _priv->tfm)
126 crypto_free_tfm(_priv->tfm);
127 kfree(priv);
128 module_put(THIS_MODULE);
129}
130
131
132static inline void xor_block(u8 *b, u8 *a, size_t len)
133{
134 int i;
135 for (i = 0; i < len; i++)
136 b[i] ^= a[i];
137}
138
139
140static void ccmp_init_blocks(struct crypto_tfm *tfm,
141 struct hostap_ieee80211_hdr *hdr,
142 u8 *pn, size_t dlen, u8 *b0, u8 *auth,
143 u8 *s0)
144{
145 u8 *pos, qc = 0;
146 size_t aad_len;
147 u16 fc;
148 int a4_included, qc_included;
149 u8 aad[2 * AES_BLOCK_LEN];
150
151 fc = le16_to_cpu(hdr->frame_control);
152 a4_included = ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) ==
153 (WLAN_FC_TODS | WLAN_FC_FROMDS));
154 qc_included = ((HOSTAP_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA) &&
155 (HOSTAP_FC_GET_STYPE(fc) & 0x08));
156 aad_len = 22;
157 if (a4_included)
158 aad_len += 6;
159 if (qc_included) {
160 pos = (u8 *) &hdr->addr4;
161 if (a4_included)
162 pos += 6;
163 qc = *pos & 0x0f;
164 aad_len += 2;
165 }
166
167 /* CCM Initial Block:
168 * Flag (Include authentication header, M=3 (8-octet MIC),
169 * L=1 (2-octet Dlen))
170 * Nonce: 0x00 | A2 | PN
171 * Dlen */
172 b0[0] = 0x59;
173 b0[1] = qc;
174 memcpy(b0 + 2, hdr->addr2, ETH_ALEN);
175 memcpy(b0 + 8, pn, CCMP_PN_LEN);
176 b0[14] = (dlen >> 8) & 0xff;
177 b0[15] = dlen & 0xff;
178
179 /* AAD:
180 * FC with bits 4..6 and 11..13 masked to zero; 14 is always one
181 * A1 | A2 | A3
182 * SC with bits 4..15 (seq#) masked to zero
183 * A4 (if present)
184 * QC (if present)
185 */
186 pos = (u8 *) hdr;
187 aad[0] = 0; /* aad_len >> 8 */
188 aad[1] = aad_len & 0xff;
189 aad[2] = pos[0] & 0x8f;
190 aad[3] = pos[1] & 0xc7;
191 memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN);
192 pos = (u8 *) &hdr->seq_ctrl;
193 aad[22] = pos[0] & 0x0f;
194 aad[23] = 0; /* all bits masked */
195 memset(aad + 24, 0, 8);
196 if (a4_included)
197 memcpy(aad + 24, hdr->addr4, ETH_ALEN);
198 if (qc_included) {
199 aad[a4_included ? 30 : 24] = qc;
200 /* rest of QC masked */
201 }
202
203 /* Start with the first block and AAD */
204 hostap_ccmp_aes_encrypt(tfm, b0, auth);
205 xor_block(auth, aad, AES_BLOCK_LEN);
206 hostap_ccmp_aes_encrypt(tfm, auth, auth);
207 xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN);
208 hostap_ccmp_aes_encrypt(tfm, auth, auth);
209 b0[0] &= 0x07;
210 b0[14] = b0[15] = 0;
211 hostap_ccmp_aes_encrypt(tfm, b0, s0);
212}
213
214
215static int hostap_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
216{
217 struct hostap_ccmp_data *key = priv;
218 int data_len, i, blocks, last, len;
219 u8 *pos, *mic;
220 struct hostap_ieee80211_hdr *hdr;
221 u8 *b0 = key->tx_b0;
222 u8 *b = key->tx_b;
223 u8 *e = key->tx_e;
224 u8 *s0 = key->tx_s0;
225
226 if (skb_headroom(skb) < CCMP_HDR_LEN ||
227 skb_tailroom(skb) < CCMP_MIC_LEN ||
228 skb->len < hdr_len)
229 return -1;
230
231 data_len = skb->len - hdr_len;
232 pos = skb_push(skb, CCMP_HDR_LEN);
233 memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
234 pos += hdr_len;
235 mic = skb_put(skb, CCMP_MIC_LEN);
236
237 i = CCMP_PN_LEN - 1;
238 while (i >= 0) {
239 key->tx_pn[i]++;
240 if (key->tx_pn[i] != 0)
241 break;
242 i--;
243 }
244
245 *pos++ = key->tx_pn[5];
246 *pos++ = key->tx_pn[4];
247 *pos++ = 0;
248 *pos++ = (key->key_idx << 6) | (1 << 5) /* Ext IV included */;
249 *pos++ = key->tx_pn[3];
250 *pos++ = key->tx_pn[2];
251 *pos++ = key->tx_pn[1];
252 *pos++ = key->tx_pn[0];
253
254 hdr = (struct hostap_ieee80211_hdr *) skb->data;
255 ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0);
256
257 blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
258 last = data_len % AES_BLOCK_LEN;
259
260 for (i = 1; i <= blocks; i++) {
261 len = (i == blocks && last) ? last : AES_BLOCK_LEN;
262 /* Authentication */
263 xor_block(b, pos, len);
264 hostap_ccmp_aes_encrypt(key->tfm, b, b);
265 /* Encryption, with counter */
266 b0[14] = (i >> 8) & 0xff;
267 b0[15] = i & 0xff;
268 hostap_ccmp_aes_encrypt(key->tfm, b0, e);
269 xor_block(pos, e, len);
270 pos += len;
271 }
272
273 for (i = 0; i < CCMP_MIC_LEN; i++)
274 mic[i] = b[i] ^ s0[i];
275
276 return 0;
277}
278
279
280static int hostap_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
281{
282 struct hostap_ccmp_data *key = priv;
283 u8 keyidx, *pos;
284 struct hostap_ieee80211_hdr *hdr;
285 u8 *b0 = key->rx_b0;
286 u8 *b = key->rx_b;
287 u8 *a = key->rx_a;
288 u8 pn[6];
289 int i, blocks, last, len;
290 size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN - CCMP_MIC_LEN;
291 u8 *mic = skb->data + skb->len - CCMP_MIC_LEN;
292
293 if (skb->len < hdr_len + CCMP_HDR_LEN + CCMP_MIC_LEN) {
294 key->dot11RSNAStatsCCMPFormatErrors++;
295 return -1;
296 }
297
298 hdr = (struct hostap_ieee80211_hdr *) skb->data;
299 pos = skb->data + hdr_len;
300 keyidx = pos[3];
301 if (!(keyidx & (1 << 5))) {
302 if (net_ratelimit()) {
303 printk(KERN_DEBUG "CCMP: received packet without ExtIV"
304 " flag from " MACSTR "\n", MAC2STR(hdr->addr2));
305 }
306 key->dot11RSNAStatsCCMPFormatErrors++;
307 return -2;
308 }
309 keyidx >>= 6;
310 if (key->key_idx != keyidx) {
311 printk(KERN_DEBUG "CCMP: RX tkey->key_idx=%d frame "
312 "keyidx=%d priv=%p\n", key->key_idx, keyidx, priv);
313 return -6;
314 }
315 if (!key->key_set) {
316 if (net_ratelimit()) {
317 printk(KERN_DEBUG "CCMP: received packet from " MACSTR
318 " with keyid=%d that does not have a configured"
319 " key\n", MAC2STR(hdr->addr2), keyidx);
320 }
321 return -3;
322 }
323
324 pn[0] = pos[7];
325 pn[1] = pos[6];
326 pn[2] = pos[5];
327 pn[3] = pos[4];
328 pn[4] = pos[1];
329 pn[5] = pos[0];
330 pos += 8;
331
332 if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) {
333 if (net_ratelimit()) {
334 printk(KERN_DEBUG "CCMP: replay detected: STA=" MACSTR
335 " previous PN %02x%02x%02x%02x%02x%02x "
336 "received PN %02x%02x%02x%02x%02x%02x\n",
337 MAC2STR(hdr->addr2), MAC2STR(key->rx_pn),
338 MAC2STR(pn));
339 }
340 key->dot11RSNAStatsCCMPReplays++;
341 return -4;
342 }
343
344 ccmp_init_blocks(key->tfm, hdr, pn, data_len, b0, a, b);
345 xor_block(mic, b, CCMP_MIC_LEN);
346
347 blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
348 last = data_len % AES_BLOCK_LEN;
349
350 for (i = 1; i <= blocks; i++) {
351 len = (i == blocks && last) ? last : AES_BLOCK_LEN;
352 /* Decrypt, with counter */
353 b0[14] = (i >> 8) & 0xff;
354 b0[15] = i & 0xff;
355 hostap_ccmp_aes_encrypt(key->tfm, b0, b);
356 xor_block(pos, b, len);
357 /* Authentication */
358 xor_block(a, pos, len);
359 hostap_ccmp_aes_encrypt(key->tfm, a, a);
360 pos += len;
361 }
362
363 if (memcmp(mic, a, CCMP_MIC_LEN) != 0) {
364 if (net_ratelimit()) {
365 printk(KERN_DEBUG "CCMP: decrypt failed: STA="
366 MACSTR "\n", MAC2STR(hdr->addr2));
367 }
368 key->dot11RSNAStatsCCMPDecryptErrors++;
369 return -5;
370 }
371
372 memcpy(key->rx_pn, pn, CCMP_PN_LEN);
373
374 /* Remove hdr and MIC */
375 memmove(skb->data + CCMP_HDR_LEN, skb->data, hdr_len);
376 skb_pull(skb, CCMP_HDR_LEN);
377 skb_trim(skb, skb->len - CCMP_MIC_LEN);
378
379 return keyidx;
380}
381
382
383static int hostap_ccmp_set_key(void *key, int len, u8 *seq, void *priv)
384{
385 struct hostap_ccmp_data *data = priv;
386 int keyidx;
387 struct crypto_tfm *tfm = data->tfm;
388
389 keyidx = data->key_idx;
390 memset(data, 0, sizeof(*data));
391 data->key_idx = keyidx;
392 data->tfm = tfm;
393 if (len == CCMP_TK_LEN) {
394 memcpy(data->key, key, CCMP_TK_LEN);
395 data->key_set = 1;
396 if (seq) {
397 data->rx_pn[0] = seq[5];
398 data->rx_pn[1] = seq[4];
399 data->rx_pn[2] = seq[3];
400 data->rx_pn[3] = seq[2];
401 data->rx_pn[4] = seq[1];
402 data->rx_pn[5] = seq[0];
403 }
404 crypto_cipher_setkey(data->tfm, data->key, CCMP_TK_LEN);
405 } else if (len == 0) {
406 data->key_set = 0;
407 } else
408 return -1;
409
410 return 0;
411}
412
413
414static int hostap_ccmp_get_key(void *key, int len, u8 *seq, void *priv)
415{
416 struct hostap_ccmp_data *data = priv;
417
418 if (len < CCMP_TK_LEN)
419 return -1;
420
421 if (!data->key_set)
422 return 0;
423 memcpy(key, data->key, CCMP_TK_LEN);
424
425 if (seq) {
426 seq[0] = data->tx_pn[5];
427 seq[1] = data->tx_pn[4];
428 seq[2] = data->tx_pn[3];
429 seq[3] = data->tx_pn[2];
430 seq[4] = data->tx_pn[1];
431 seq[5] = data->tx_pn[0];
432 }
433
434 return CCMP_TK_LEN;
435}
436
437
438static char * hostap_ccmp_print_stats(char *p, void *priv)
439{
440 struct hostap_ccmp_data *ccmp = priv;
441 p += sprintf(p, "key[%d] alg=CCMP key_set=%d "
442 "tx_pn=%02x%02x%02x%02x%02x%02x "
443 "rx_pn=%02x%02x%02x%02x%02x%02x "
444 "format_errors=%d replays=%d decrypt_errors=%d\n",
445 ccmp->key_idx, ccmp->key_set,
446 MAC2STR(ccmp->tx_pn), MAC2STR(ccmp->rx_pn),
447 ccmp->dot11RSNAStatsCCMPFormatErrors,
448 ccmp->dot11RSNAStatsCCMPReplays,
449 ccmp->dot11RSNAStatsCCMPDecryptErrors);
450
451 return p;
452}
453
454
455static struct hostap_crypto_ops hostap_crypt_ccmp = {
456 .name = "CCMP",
457 .init = hostap_ccmp_init,
458 .deinit = hostap_ccmp_deinit,
459 .encrypt_mpdu = hostap_ccmp_encrypt,
460 .decrypt_mpdu = hostap_ccmp_decrypt,
461 .encrypt_msdu = NULL,
462 .decrypt_msdu = NULL,
463 .set_key = hostap_ccmp_set_key,
464 .get_key = hostap_ccmp_get_key,
465 .print_stats = hostap_ccmp_print_stats,
466 .extra_prefix_len = CCMP_HDR_LEN,
467 .extra_postfix_len = CCMP_MIC_LEN
468};
469
470
471static int __init hostap_crypto_ccmp_init(void)
472{
473 if (hostap_register_crypto_ops(&hostap_crypt_ccmp) < 0)
474 return -1;
475
476 return 0;
477}
478
479
480static void __exit hostap_crypto_ccmp_exit(void)
481{
482 hostap_unregister_crypto_ops(&hostap_crypt_ccmp);
483}
484
485
486module_init(hostap_crypto_ccmp_init);
487module_exit(hostap_crypto_ccmp_exit);
diff --git a/drivers/net/wireless/hostap/hostap_crypt_tkip.c b/drivers/net/wireless/hostap/hostap_crypt_tkip.c
deleted file mode 100644
index fcf1a014f4ac..000000000000
--- a/drivers/net/wireless/hostap/hostap_crypt_tkip.c
+++ /dev/null
@@ -1,697 +0,0 @@
1/*
2 * Host AP crypt: host-based TKIP encryption implementation for Host AP driver
3 *
4 * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation. See README and COPYING for
9 * more details.
10 */
11
12#include <linux/config.h>
13#include <linux/version.h>
14#include <linux/module.h>
15#include <linux/init.h>
16#include <linux/slab.h>
17#include <linux/random.h>
18#include <linux/skbuff.h>
19#include <linux/netdevice.h>
20#include <linux/if_ether.h>
21#include <linux/if_arp.h>
22#include <linux/wireless.h>
23#include <net/iw_handler.h>
24#include <asm/string.h>
25
26#include "hostap_crypt.h"
27#include "hostap_wlan.h"
28#include "hostap_80211.h"
29#include "hostap_config.h"
30
31#ifndef CONFIG_CRYPTO
32#error CONFIG_CRYPTO is required to build this module.
33#endif
34#include <linux/crypto.h>
35#include <asm/scatterlist.h>
36#include <linux/crc32.h>
37
38MODULE_AUTHOR("Jouni Malinen");
39MODULE_DESCRIPTION("Host AP crypt: TKIP");
40MODULE_LICENSE("GPL");
41MODULE_VERSION(PRISM2_VERSION);
42
43
44struct hostap_tkip_data {
45#define TKIP_KEY_LEN 32
46 u8 key[TKIP_KEY_LEN];
47 int key_set;
48
49 u32 tx_iv32;
50 u16 tx_iv16;
51 u16 tx_ttak[5];
52 int tx_phase1_done;
53
54 u32 rx_iv32;
55 u16 rx_iv16;
56 u16 rx_ttak[5];
57 int rx_phase1_done;
58 u32 rx_iv32_new;
59 u16 rx_iv16_new;
60
61 u32 dot11RSNAStatsTKIPReplays;
62 u32 dot11RSNAStatsTKIPICVErrors;
63 u32 dot11RSNAStatsTKIPLocalMICFailures;
64
65 int key_idx;
66
67 struct crypto_tfm *tfm_arc4;
68 struct crypto_tfm *tfm_michael;
69
70 /* scratch buffers for virt_to_page() (crypto API) */
71 u8 rx_hdr[16], tx_hdr[16];
72};
73
74
75static void * hostap_tkip_init(int key_idx)
76{
77 struct hostap_tkip_data *priv;
78
79 if (!try_module_get(THIS_MODULE))
80 return NULL;
81
82 priv = (struct hostap_tkip_data *) kmalloc(sizeof(*priv), GFP_ATOMIC);
83 if (priv == NULL)
84 goto fail;
85 memset(priv, 0, sizeof(*priv));
86 priv->key_idx = key_idx;
87
88 priv->tfm_arc4 = crypto_alloc_tfm("arc4", 0);
89 if (priv->tfm_arc4 == NULL) {
90 printk(KERN_DEBUG "hostap_crypt_tkip: could not allocate "
91 "crypto API arc4\n");
92 goto fail;
93 }
94
95 priv->tfm_michael = crypto_alloc_tfm("michael_mic", 0);
96 if (priv->tfm_michael == NULL) {
97 printk(KERN_DEBUG "hostap_crypt_tkip: could not allocate "
98 "crypto API michael_mic\n");
99 goto fail;
100 }
101
102 return priv;
103
104fail:
105 if (priv) {
106 if (priv->tfm_michael)
107 crypto_free_tfm(priv->tfm_michael);
108 if (priv->tfm_arc4)
109 crypto_free_tfm(priv->tfm_arc4);
110 kfree(priv);
111 }
112 module_put(THIS_MODULE);
113 return NULL;
114}
115
116
117static void hostap_tkip_deinit(void *priv)
118{
119 struct hostap_tkip_data *_priv = priv;
120 if (_priv && _priv->tfm_michael)
121 crypto_free_tfm(_priv->tfm_michael);
122 if (_priv && _priv->tfm_arc4)
123 crypto_free_tfm(_priv->tfm_arc4);
124 kfree(priv);
125 module_put(THIS_MODULE);
126}
127
128
129static inline u16 RotR1(u16 val)
130{
131 return (val >> 1) | (val << 15);
132}
133
134
135static inline u8 Lo8(u16 val)
136{
137 return val & 0xff;
138}
139
140
141static inline u8 Hi8(u16 val)
142{
143 return val >> 8;
144}
145
146
147static inline u16 Lo16(u32 val)
148{
149 return val & 0xffff;
150}
151
152
153static inline u16 Hi16(u32 val)
154{
155 return val >> 16;
156}
157
158
159static inline u16 Mk16(u8 hi, u8 lo)
160{
161 return lo | (((u16) hi) << 8);
162}
163
164
165static inline u16 Mk16_le(u16 *v)
166{
167 return le16_to_cpu(*v);
168}
169
170
171static const u16 Sbox[256] =
172{
173 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
174 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
175 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
176 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
177 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
178 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
179 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
180 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
181 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
182 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
183 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
184 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
185 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
186 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
187 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
188 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
189 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
190 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
191 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
192 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
193 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
194 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
195 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
196 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
197 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
198 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
199 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
200 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
201 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
202 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
203 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
204 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
205};
206
207
208static inline u16 _S_(u16 v)
209{
210 u16 t = Sbox[Hi8(v)];
211 return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8));
212}
213
214
215#define PHASE1_LOOP_COUNT 8
216
217static void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32)
218{
219 int i, j;
220
221 /* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */
222 TTAK[0] = Lo16(IV32);
223 TTAK[1] = Hi16(IV32);
224 TTAK[2] = Mk16(TA[1], TA[0]);
225 TTAK[3] = Mk16(TA[3], TA[2]);
226 TTAK[4] = Mk16(TA[5], TA[4]);
227
228 for (i = 0; i < PHASE1_LOOP_COUNT; i++) {
229 j = 2 * (i & 1);
230 TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j]));
231 TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j]));
232 TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j]));
233 TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j]));
234 TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i;
235 }
236}
237
238
239static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK,
240 u16 IV16)
241{
242 /* Make temporary area overlap WEP seed so that the final copy can be
243 * avoided on little endian hosts. */
244 u16 *PPK = (u16 *) &WEPSeed[4];
245
246 /* Step 1 - make copy of TTAK and bring in TSC */
247 PPK[0] = TTAK[0];
248 PPK[1] = TTAK[1];
249 PPK[2] = TTAK[2];
250 PPK[3] = TTAK[3];
251 PPK[4] = TTAK[4];
252 PPK[5] = TTAK[4] + IV16;
253
254 /* Step 2 - 96-bit bijective mixing using S-box */
255 PPK[0] += _S_(PPK[5] ^ Mk16_le((u16 *) &TK[0]));
256 PPK[1] += _S_(PPK[0] ^ Mk16_le((u16 *) &TK[2]));
257 PPK[2] += _S_(PPK[1] ^ Mk16_le((u16 *) &TK[4]));
258 PPK[3] += _S_(PPK[2] ^ Mk16_le((u16 *) &TK[6]));
259 PPK[4] += _S_(PPK[3] ^ Mk16_le((u16 *) &TK[8]));
260 PPK[5] += _S_(PPK[4] ^ Mk16_le((u16 *) &TK[10]));
261
262 PPK[0] += RotR1(PPK[5] ^ Mk16_le((u16 *) &TK[12]));
263 PPK[1] += RotR1(PPK[0] ^ Mk16_le((u16 *) &TK[14]));
264 PPK[2] += RotR1(PPK[1]);
265 PPK[3] += RotR1(PPK[2]);
266 PPK[4] += RotR1(PPK[3]);
267 PPK[5] += RotR1(PPK[4]);
268
269 /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value
270 * WEPSeed[0..2] is transmitted as WEP IV */
271 WEPSeed[0] = Hi8(IV16);
272 WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F;
273 WEPSeed[2] = Lo8(IV16);
274 WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((u16 *) &TK[0])) >> 1);
275
276#ifdef __BIG_ENDIAN
277 {
278 int i;
279 for (i = 0; i < 6; i++)
280 PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8);
281 }
282#endif
283}
284
285
286static int hostap_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
287{
288 struct hostap_tkip_data *tkey = priv;
289 int len;
290 u8 rc4key[16], *pos, *icv;
291 struct hostap_ieee80211_hdr *hdr;
292 u32 crc;
293 struct scatterlist sg;
294
295 if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 ||
296 skb->len < hdr_len)
297 return -1;
298
299 hdr = (struct hostap_ieee80211_hdr *) skb->data;
300 if (!tkey->tx_phase1_done) {
301 tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
302 tkey->tx_iv32);
303 tkey->tx_phase1_done = 1;
304 }
305 tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);
306
307 len = skb->len - hdr_len;
308 pos = skb_push(skb, 8);
309 memmove(pos, pos + 8, hdr_len);
310 pos += hdr_len;
311 icv = skb_put(skb, 4);
312
313 *pos++ = rc4key[0];
314 *pos++ = rc4key[1];
315 *pos++ = rc4key[2];
316 *pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */;
317 *pos++ = tkey->tx_iv32 & 0xff;
318 *pos++ = (tkey->tx_iv32 >> 8) & 0xff;
319 *pos++ = (tkey->tx_iv32 >> 16) & 0xff;
320 *pos++ = (tkey->tx_iv32 >> 24) & 0xff;
321
322 crc = ~crc32_le(~0, pos, len);
323 icv[0] = crc;
324 icv[1] = crc >> 8;
325 icv[2] = crc >> 16;
326 icv[3] = crc >> 24;
327
328 crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
329 sg.page = virt_to_page(pos);
330 sg.offset = offset_in_page(pos);
331 sg.length = len + 4;
332 crypto_cipher_encrypt(tkey->tfm_arc4, &sg, &sg, len + 4);
333
334 tkey->tx_iv16++;
335 if (tkey->tx_iv16 == 0) {
336 tkey->tx_phase1_done = 0;
337 tkey->tx_iv32++;
338 }
339
340 return 0;
341}
342
343
344static int hostap_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
345{
346 struct hostap_tkip_data *tkey = priv;
347 u8 rc4key[16];
348 u8 keyidx, *pos, icv[4];
349 u32 iv32;
350 u16 iv16;
351 struct hostap_ieee80211_hdr *hdr;
352 u32 crc;
353 struct scatterlist sg;
354 int plen;
355
356 if (skb->len < hdr_len + 8 + 4)
357 return -1;
358
359 hdr = (struct hostap_ieee80211_hdr *) skb->data;
360 pos = skb->data + hdr_len;
361 keyidx = pos[3];
362 if (!(keyidx & (1 << 5))) {
363 if (net_ratelimit()) {
364 printk(KERN_DEBUG "TKIP: received packet without ExtIV"
365 " flag from " MACSTR "\n", MAC2STR(hdr->addr2));
366 }
367 return -2;
368 }
369 keyidx >>= 6;
370 if (tkey->key_idx != keyidx) {
371 printk(KERN_DEBUG "TKIP: RX tkey->key_idx=%d frame "
372 "keyidx=%d priv=%p\n", tkey->key_idx, keyidx, priv);
373 return -6;
374 }
375 if (!tkey->key_set) {
376 if (net_ratelimit()) {
377 printk(KERN_DEBUG "TKIP: received packet from " MACSTR
378 " with keyid=%d that does not have a configured"
379 " key\n", MAC2STR(hdr->addr2), keyidx);
380 }
381 return -3;
382 }
383 iv16 = (pos[0] << 8) | pos[2];
384 iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
385 pos += 8;
386
387 if (iv32 < tkey->rx_iv32 ||
388 (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {
389 if (net_ratelimit()) {
390 printk(KERN_DEBUG "TKIP: replay detected: STA=" MACSTR
391 " previous TSC %08x%04x received TSC "
392 "%08x%04x\n", MAC2STR(hdr->addr2),
393 tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
394 }
395 tkey->dot11RSNAStatsTKIPReplays++;
396 return -4;
397 }
398
399 if (iv32 != tkey->rx_iv32 || !tkey->rx_phase1_done) {
400 tkip_mixing_phase1(tkey->rx_ttak, tkey->key, hdr->addr2, iv32);
401 tkey->rx_phase1_done = 1;
402 }
403 tkip_mixing_phase2(rc4key, tkey->key, tkey->rx_ttak, iv16);
404
405 plen = skb->len - hdr_len - 12;
406
407 crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
408 sg.page = virt_to_page(pos);
409 sg.offset = offset_in_page(pos);
410 sg.length = plen + 4;
411 crypto_cipher_decrypt(tkey->tfm_arc4, &sg, &sg, plen + 4);
412
413 crc = ~crc32_le(~0, pos, plen);
414 icv[0] = crc;
415 icv[1] = crc >> 8;
416 icv[2] = crc >> 16;
417 icv[3] = crc >> 24;
418 if (memcmp(icv, pos + plen, 4) != 0) {
419 if (iv32 != tkey->rx_iv32) {
420 /* Previously cached Phase1 result was already lost, so
421 * it needs to be recalculated for the next packet. */
422 tkey->rx_phase1_done = 0;
423 }
424 if (net_ratelimit()) {
425 printk(KERN_DEBUG "TKIP: ICV error detected: STA="
426 MACSTR "\n", MAC2STR(hdr->addr2));
427 }
428 tkey->dot11RSNAStatsTKIPICVErrors++;
429 return -5;
430 }
431
432 /* Update real counters only after Michael MIC verification has
433 * completed */
434 tkey->rx_iv32_new = iv32;
435 tkey->rx_iv16_new = iv16;
436
437 /* Remove IV and ICV */
438 memmove(skb->data + 8, skb->data, hdr_len);
439 skb_pull(skb, 8);
440 skb_trim(skb, skb->len - 4);
441
442 return keyidx;
443}
444
445
446static int michael_mic(struct hostap_tkip_data *tkey, u8 *key, u8 *hdr,
447 u8 *data, size_t data_len, u8 *mic)
448{
449 struct scatterlist sg[2];
450
451 if (tkey->tfm_michael == NULL) {
452 printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
453 return -1;
454 }
455 sg[0].page = virt_to_page(hdr);
456 sg[0].offset = offset_in_page(hdr);
457 sg[0].length = 16;
458
459 sg[1].page = virt_to_page(data);
460 sg[1].offset = offset_in_page(data);
461 sg[1].length = data_len;
462
463 crypto_digest_init(tkey->tfm_michael);
464 crypto_digest_setkey(tkey->tfm_michael, key, 8);
465 crypto_digest_update(tkey->tfm_michael, sg, 2);
466 crypto_digest_final(tkey->tfm_michael, mic);
467
468 return 0;
469}
470
471
472static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr)
473{
474 struct hostap_ieee80211_hdr *hdr11;
475
476 hdr11 = (struct hostap_ieee80211_hdr *) skb->data;
477 switch (le16_to_cpu(hdr11->frame_control) &
478 (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
479 case WLAN_FC_TODS:
480 memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
481 memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
482 break;
483 case WLAN_FC_FROMDS:
484 memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
485 memcpy(hdr + ETH_ALEN, hdr11->addr3, ETH_ALEN); /* SA */
486 break;
487 case WLAN_FC_FROMDS | WLAN_FC_TODS:
488 memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
489 memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */
490 break;
491 case 0:
492 memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
493 memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
494 break;
495 }
496
497 hdr[12] = 0; /* priority */
498 hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */
499}
500
501
502static int hostap_michael_mic_add(struct sk_buff *skb, int hdr_len, void *priv)
503{
504 struct hostap_tkip_data *tkey = priv;
505 u8 *pos;
506
507 if (skb_tailroom(skb) < 8 || skb->len < hdr_len) {
508 printk(KERN_DEBUG "Invalid packet for Michael MIC add "
509 "(tailroom=%d hdr_len=%d skb->len=%d)\n",
510 skb_tailroom(skb), hdr_len, skb->len);
511 return -1;
512 }
513
514 michael_mic_hdr(skb, tkey->tx_hdr);
515 pos = skb_put(skb, 8);
516 if (michael_mic(tkey, &tkey->key[16], tkey->tx_hdr,
517 skb->data + hdr_len, skb->len - 8 - hdr_len, pos))
518 return -1;
519
520 return 0;
521}
522
523
524static void hostap_michael_mic_failure(struct net_device *dev,
525 struct hostap_ieee80211_hdr *hdr,
526 int keyidx)
527{
528 union iwreq_data wrqu;
529 char buf[128];
530
531 /* TODO: needed parameters: count, keyid, key type, src address, TSC */
532 sprintf(buf, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr="
533 MACSTR ")", keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni",
534 MAC2STR(hdr->addr2));
535 memset(&wrqu, 0, sizeof(wrqu));
536 wrqu.data.length = strlen(buf);
537 wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
538}
539
540
541static int hostap_michael_mic_verify(struct sk_buff *skb, int keyidx,
542 int hdr_len, void *priv)
543{
544 struct hostap_tkip_data *tkey = priv;
545 u8 mic[8];
546
547 if (!tkey->key_set)
548 return -1;
549
550 michael_mic_hdr(skb, tkey->rx_hdr);
551 if (michael_mic(tkey, &tkey->key[24], tkey->rx_hdr,
552 skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
553 return -1;
554 if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
555 struct hostap_ieee80211_hdr *hdr;
556 hdr = (struct hostap_ieee80211_hdr *) skb->data;
557 printk(KERN_DEBUG "%s: Michael MIC verification failed for "
558 "MSDU from " MACSTR " keyidx=%d\n",
559 skb->dev ? skb->dev->name : "N/A", MAC2STR(hdr->addr2),
560 keyidx);
561 if (skb->dev)
562 hostap_michael_mic_failure(skb->dev, hdr, keyidx);
563 tkey->dot11RSNAStatsTKIPLocalMICFailures++;
564 return -1;
565 }
566
567 /* Update TSC counters for RX now that the packet verification has
568 * completed. */
569 tkey->rx_iv32 = tkey->rx_iv32_new;
570 tkey->rx_iv16 = tkey->rx_iv16_new;
571
572 skb_trim(skb, skb->len - 8);
573
574 return 0;
575}
576
577
578static int hostap_tkip_set_key(void *key, int len, u8 *seq, void *priv)
579{
580 struct hostap_tkip_data *tkey = priv;
581 int keyidx;
582 struct crypto_tfm *tfm = tkey->tfm_michael;
583 struct crypto_tfm *tfm2 = tkey->tfm_arc4;
584
585 keyidx = tkey->key_idx;
586 memset(tkey, 0, sizeof(*tkey));
587 tkey->key_idx = keyidx;
588 tkey->tfm_michael = tfm;
589 tkey->tfm_arc4 = tfm2;
590 if (len == TKIP_KEY_LEN) {
591 memcpy(tkey->key, key, TKIP_KEY_LEN);
592 tkey->key_set = 1;
593 tkey->tx_iv16 = 1; /* TSC is initialized to 1 */
594 if (seq) {
595 tkey->rx_iv32 = (seq[5] << 24) | (seq[4] << 16) |
596 (seq[3] << 8) | seq[2];
597 tkey->rx_iv16 = (seq[1] << 8) | seq[0];
598 }
599 } else if (len == 0) {
600 tkey->key_set = 0;
601 } else
602 return -1;
603
604 return 0;
605}
606
607
608static int hostap_tkip_get_key(void *key, int len, u8 *seq, void *priv)
609{
610 struct hostap_tkip_data *tkey = priv;
611
612 if (len < TKIP_KEY_LEN)
613 return -1;
614
615 if (!tkey->key_set)
616 return 0;
617 memcpy(key, tkey->key, TKIP_KEY_LEN);
618
619 if (seq) {
620 /* Return the sequence number of the last transmitted frame. */
621 u16 iv16 = tkey->tx_iv16;
622 u32 iv32 = tkey->tx_iv32;
623 if (iv16 == 0)
624 iv32--;
625 iv16--;
626 seq[0] = tkey->tx_iv16;
627 seq[1] = tkey->tx_iv16 >> 8;
628 seq[2] = tkey->tx_iv32;
629 seq[3] = tkey->tx_iv32 >> 8;
630 seq[4] = tkey->tx_iv32 >> 16;
631 seq[5] = tkey->tx_iv32 >> 24;
632 }
633
634 return TKIP_KEY_LEN;
635}
636
637
638static char * hostap_tkip_print_stats(char *p, void *priv)
639{
640 struct hostap_tkip_data *tkip = priv;
641 p += sprintf(p, "key[%d] alg=TKIP key_set=%d "
642 "tx_pn=%02x%02x%02x%02x%02x%02x "
643 "rx_pn=%02x%02x%02x%02x%02x%02x "
644 "replays=%d icv_errors=%d local_mic_failures=%d\n",
645 tkip->key_idx, tkip->key_set,
646 (tkip->tx_iv32 >> 24) & 0xff,
647 (tkip->tx_iv32 >> 16) & 0xff,
648 (tkip->tx_iv32 >> 8) & 0xff,
649 tkip->tx_iv32 & 0xff,
650 (tkip->tx_iv16 >> 8) & 0xff,
651 tkip->tx_iv16 & 0xff,
652 (tkip->rx_iv32 >> 24) & 0xff,
653 (tkip->rx_iv32 >> 16) & 0xff,
654 (tkip->rx_iv32 >> 8) & 0xff,
655 tkip->rx_iv32 & 0xff,
656 (tkip->rx_iv16 >> 8) & 0xff,
657 tkip->rx_iv16 & 0xff,
658 tkip->dot11RSNAStatsTKIPReplays,
659 tkip->dot11RSNAStatsTKIPICVErrors,
660 tkip->dot11RSNAStatsTKIPLocalMICFailures);
661 return p;
662}
663
664
665static struct hostap_crypto_ops hostap_crypt_tkip = {
666 .name = "TKIP",
667 .init = hostap_tkip_init,
668 .deinit = hostap_tkip_deinit,
669 .encrypt_mpdu = hostap_tkip_encrypt,
670 .decrypt_mpdu = hostap_tkip_decrypt,
671 .encrypt_msdu = hostap_michael_mic_add,
672 .decrypt_msdu = hostap_michael_mic_verify,
673 .set_key = hostap_tkip_set_key,
674 .get_key = hostap_tkip_get_key,
675 .print_stats = hostap_tkip_print_stats,
676 .extra_prefix_len = 4 + 4 /* IV + ExtIV */,
677 .extra_postfix_len = 8 + 4 /* MIC + ICV */
678};
679
680
681static int __init hostap_crypto_tkip_init(void)
682{
683 if (hostap_register_crypto_ops(&hostap_crypt_tkip) < 0)
684 return -1;
685
686 return 0;
687}
688
689
690static void __exit hostap_crypto_tkip_exit(void)
691{
692 hostap_unregister_crypto_ops(&hostap_crypt_tkip);
693}
694
695
696module_init(hostap_crypto_tkip_init);
697module_exit(hostap_crypto_tkip_exit);
diff --git a/drivers/net/wireless/hostap/hostap_crypt_wep.c b/drivers/net/wireless/hostap/hostap_crypt_wep.c
deleted file mode 100644
index 66c403f17631..000000000000
--- a/drivers/net/wireless/hostap/hostap_crypt_wep.c
+++ /dev/null
@@ -1,283 +0,0 @@
1/*
2 * Host AP crypt: host-based WEP encryption implementation for Host AP driver
3 *
4 * Copyright (c) 2002-2004, Jouni Malinen <jkmaline@cc.hut.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation. See README and COPYING for
9 * more details.
10 */
11
12#include <linux/config.h>
13#include <linux/version.h>
14#include <linux/module.h>
15#include <linux/init.h>
16#include <linux/slab.h>
17#include <linux/random.h>
18#include <linux/skbuff.h>
19#include <asm/string.h>
20
21#include "hostap_crypt.h"
22#include "hostap_config.h"
23
24#ifndef CONFIG_CRYPTO
25#error CONFIG_CRYPTO is required to build this module.
26#endif
27#include <linux/crypto.h>
28#include <asm/scatterlist.h>
29#include <linux/crc32.h>
30
31MODULE_AUTHOR("Jouni Malinen");
32MODULE_DESCRIPTION("Host AP crypt: WEP");
33MODULE_LICENSE("GPL");
34MODULE_VERSION(PRISM2_VERSION);
35
36
37struct prism2_wep_data {
38 u32 iv;
39#define WEP_KEY_LEN 13
40 u8 key[WEP_KEY_LEN + 1];
41 u8 key_len;
42 u8 key_idx;
43 struct crypto_tfm *tfm;
44};
45
46
47static void * prism2_wep_init(int keyidx)
48{
49 struct prism2_wep_data *priv;
50
51 if (!try_module_get(THIS_MODULE))
52 return NULL;
53
54 priv = (struct prism2_wep_data *) kmalloc(sizeof(*priv), GFP_ATOMIC);
55 if (priv == NULL)
56 goto fail;
57 memset(priv, 0, sizeof(*priv));
58 priv->key_idx = keyidx;
59
60 priv->tfm = crypto_alloc_tfm("arc4", 0);
61 if (priv->tfm == NULL) {
62 printk(KERN_DEBUG "hostap_crypt_wep: could not allocate "
63 "crypto API arc4\n");
64 goto fail;
65 }
66
67 /* start WEP IV from a random value */
68 get_random_bytes(&priv->iv, 4);
69
70 return priv;
71
72fail:
73 if (priv) {
74 if (priv->tfm)
75 crypto_free_tfm(priv->tfm);
76 kfree(priv);
77 }
78 module_put(THIS_MODULE);
79 return NULL;
80}
81
82
83static void prism2_wep_deinit(void *priv)
84{
85 struct prism2_wep_data *_priv = priv;
86 if (_priv && _priv->tfm)
87 crypto_free_tfm(_priv->tfm);
88 kfree(priv);
89 module_put(THIS_MODULE);
90}
91
92
93/* Perform WEP encryption on given skb that has at least 4 bytes of headroom
94 * for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted,
95 * so the payload length increases with 8 bytes.
96 *
97 * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
98 */
99static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
100{
101 struct prism2_wep_data *wep = priv;
102 u32 crc, klen, len;
103 u8 key[WEP_KEY_LEN + 3];
104 u8 *pos, *icv;
105 struct scatterlist sg;
106
107 if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 ||
108 skb->len < hdr_len)
109 return -1;
110
111 len = skb->len - hdr_len;
112 pos = skb_push(skb, 4);
113 memmove(pos, pos + 4, hdr_len);
114 pos += hdr_len;
115
116 klen = 3 + wep->key_len;
117
118 wep->iv++;
119
120 /* Fluhrer, Mantin, and Shamir have reported weaknesses in the key
121 * scheduling algorithm of RC4. At least IVs (KeyByte + 3, 0xff, N)
122 * can be used to speedup attacks, so avoid using them. */
123 if ((wep->iv & 0xff00) == 0xff00) {
124 u8 B = (wep->iv >> 16) & 0xff;
125 if (B >= 3 && B < klen)
126 wep->iv += 0x0100;
127 }
128
129 /* Prepend 24-bit IV to RC4 key and TX frame */
130 *pos++ = key[0] = (wep->iv >> 16) & 0xff;
131 *pos++ = key[1] = (wep->iv >> 8) & 0xff;
132 *pos++ = key[2] = wep->iv & 0xff;
133 *pos++ = wep->key_idx << 6;
134
135 /* Copy rest of the WEP key (the secret part) */
136 memcpy(key + 3, wep->key, wep->key_len);
137
138 /* Append little-endian CRC32 and encrypt it to produce ICV */
139 crc = ~crc32_le(~0, pos, len);
140 icv = skb_put(skb, 4);
141 icv[0] = crc;
142 icv[1] = crc >> 8;
143 icv[2] = crc >> 16;
144 icv[3] = crc >> 24;
145
146 crypto_cipher_setkey(wep->tfm, key, klen);
147 sg.page = virt_to_page(pos);
148 sg.offset = offset_in_page(pos);
149 sg.length = len + 4;
150 crypto_cipher_encrypt(wep->tfm, &sg, &sg, len + 4);
151
152 return 0;
153}
154
155
156/* Perform WEP decryption on given buffer. Buffer includes whole WEP part of
157 * the frame: IV (4 bytes), encrypted payload (including SNAP header),
158 * ICV (4 bytes). len includes both IV and ICV.
159 *
160 * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on
161 * failure. If frame is OK, IV and ICV will be removed.
162 */
163static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
164{
165 struct prism2_wep_data *wep = priv;
166 u32 crc, klen, plen;
167 u8 key[WEP_KEY_LEN + 3];
168 u8 keyidx, *pos, icv[4];
169 struct scatterlist sg;
170
171 if (skb->len < hdr_len + 8)
172 return -1;
173
174 pos = skb->data + hdr_len;
175 key[0] = *pos++;
176 key[1] = *pos++;
177 key[2] = *pos++;
178 keyidx = *pos++ >> 6;
179 if (keyidx != wep->key_idx)
180 return -1;
181
182 klen = 3 + wep->key_len;
183
184 /* Copy rest of the WEP key (the secret part) */
185 memcpy(key + 3, wep->key, wep->key_len);
186
187 /* Apply RC4 to data and compute CRC32 over decrypted data */
188 plen = skb->len - hdr_len - 8;
189
190 crypto_cipher_setkey(wep->tfm, key, klen);
191 sg.page = virt_to_page(pos);
192 sg.offset = offset_in_page(pos);
193 sg.length = plen + 4;
194 crypto_cipher_decrypt(wep->tfm, &sg, &sg, plen + 4);
195
196 crc = ~crc32_le(~0, pos, plen);
197 icv[0] = crc;
198 icv[1] = crc >> 8;
199 icv[2] = crc >> 16;
200 icv[3] = crc >> 24;
201 if (memcmp(icv, pos + plen, 4) != 0) {
202 /* ICV mismatch - drop frame */
203 return -2;
204 }
205
206 /* Remove IV and ICV */
207 memmove(skb->data + 4, skb->data, hdr_len);
208 skb_pull(skb, 4);
209 skb_trim(skb, skb->len - 4);
210
211 return 0;
212}
213
214
215static int prism2_wep_set_key(void *key, int len, u8 *seq, void *priv)
216{
217 struct prism2_wep_data *wep = priv;
218
219 if (len < 0 || len > WEP_KEY_LEN)
220 return -1;
221
222 memcpy(wep->key, key, len);
223 wep->key_len = len;
224
225 return 0;
226}
227
228
229static int prism2_wep_get_key(void *key, int len, u8 *seq, void *priv)
230{
231 struct prism2_wep_data *wep = priv;
232
233 if (len < wep->key_len)
234 return -1;
235
236 memcpy(key, wep->key, wep->key_len);
237
238 return wep->key_len;
239}
240
241
242static char * prism2_wep_print_stats(char *p, void *priv)
243{
244 struct prism2_wep_data *wep = priv;
245 p += sprintf(p, "key[%d] alg=WEP len=%d\n",
246 wep->key_idx, wep->key_len);
247 return p;
248}
249
250
251static struct hostap_crypto_ops hostap_crypt_wep = {
252 .name = "WEP",
253 .init = prism2_wep_init,
254 .deinit = prism2_wep_deinit,
255 .encrypt_mpdu = prism2_wep_encrypt,
256 .decrypt_mpdu = prism2_wep_decrypt,
257 .encrypt_msdu = NULL,
258 .decrypt_msdu = NULL,
259 .set_key = prism2_wep_set_key,
260 .get_key = prism2_wep_get_key,
261 .print_stats = prism2_wep_print_stats,
262 .extra_prefix_len = 4 /* IV */,
263 .extra_postfix_len = 4 /* ICV */
264};
265
266
267static int __init hostap_crypto_wep_init(void)
268{
269 if (hostap_register_crypto_ops(&hostap_crypt_wep) < 0)
270 return -1;
271
272 return 0;
273}
274
275
276static void __exit hostap_crypto_wep_exit(void)
277{
278 hostap_unregister_crypto_ops(&hostap_crypt_wep);
279}
280
281
282module_init(hostap_crypto_wep_init);
283module_exit(hostap_crypto_wep_exit);
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index 72a8a19ad8c0..dc31f5351b36 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -4,7 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen 5 * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
6 * <jkmaline@cc.hut.fi> 6 * <jkmaline@cc.hut.fi>
7 * Copyright (c) 2002-2004, Jouni Malinen <jkmaline@cc.hut.fi> 7 * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi>
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as 10 * it under the terms of the GNU General Public License version 2 as
@@ -2967,11 +2967,11 @@ static void prism2_check_sta_fw_version(local_info_t *local)
2967static void prism2_crypt_deinit_entries(local_info_t *local, int force) 2967static void prism2_crypt_deinit_entries(local_info_t *local, int force)
2968{ 2968{
2969 struct list_head *ptr, *n; 2969 struct list_head *ptr, *n;
2970 struct prism2_crypt_data *entry; 2970 struct ieee80211_crypt_data *entry;
2971 2971
2972 for (ptr = local->crypt_deinit_list.next, n = ptr->next; 2972 for (ptr = local->crypt_deinit_list.next, n = ptr->next;
2973 ptr != &local->crypt_deinit_list; ptr = n, n = ptr->next) { 2973 ptr != &local->crypt_deinit_list; ptr = n, n = ptr->next) {
2974 entry = list_entry(ptr, struct prism2_crypt_data, list); 2974 entry = list_entry(ptr, struct ieee80211_crypt_data, list);
2975 2975
2976 if (atomic_read(&entry->refcnt) != 0 && !force) 2976 if (atomic_read(&entry->refcnt) != 0 && !force)
2977 continue; 2977 continue;
@@ -3531,7 +3531,7 @@ static void prism2_free_local_data(struct net_device *dev)
3531 prism2_callback(local, PRISM2_CALLBACK_DISABLE); 3531 prism2_callback(local, PRISM2_CALLBACK_DISABLE);
3532 3532
3533 for (i = 0; i < WEP_KEYS; i++) { 3533 for (i = 0; i < WEP_KEYS; i++) {
3534 struct prism2_crypt_data *crypt = local->crypt[i]; 3534 struct ieee80211_crypt_data *crypt = local->crypt[i];
3535 if (crypt) { 3535 if (crypt) {
3536 if (crypt->ops) 3536 if (crypt->ops)
3537 crypt->ops->deinit(crypt->priv); 3537 crypt->ops->deinit(crypt->priv);
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index bbed1e634583..f892aa87b13e 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -115,9 +115,9 @@ static int prism2_get_name(struct net_device *dev,
115 115
116 116
117static void prism2_crypt_delayed_deinit(local_info_t *local, 117static void prism2_crypt_delayed_deinit(local_info_t *local,
118 struct prism2_crypt_data **crypt) 118 struct ieee80211_crypt_data **crypt)
119{ 119{
120 struct prism2_crypt_data *tmp; 120 struct ieee80211_crypt_data *tmp;
121 unsigned long flags; 121 unsigned long flags;
122 122
123 tmp = *crypt; 123 tmp = *crypt;
@@ -147,7 +147,7 @@ static int prism2_ioctl_siwencode(struct net_device *dev,
147 struct hostap_interface *iface; 147 struct hostap_interface *iface;
148 local_info_t *local; 148 local_info_t *local;
149 int i; 149 int i;
150 struct prism2_crypt_data **crypt; 150 struct ieee80211_crypt_data **crypt;
151 151
152 iface = netdev_priv(dev); 152 iface = netdev_priv(dev);
153 local = iface->local; 153 local = iface->local;
@@ -175,18 +175,19 @@ static int prism2_ioctl_siwencode(struct net_device *dev,
175 } 175 }
176 176
177 if (*crypt == NULL) { 177 if (*crypt == NULL) {
178 struct prism2_crypt_data *new_crypt; 178 struct ieee80211_crypt_data *new_crypt;
179 179
180 /* take WEP into use */ 180 /* take WEP into use */
181 new_crypt = (struct prism2_crypt_data *) 181 new_crypt = (struct ieee80211_crypt_data *)
182 kmalloc(sizeof(struct prism2_crypt_data), GFP_KERNEL); 182 kmalloc(sizeof(struct ieee80211_crypt_data),
183 GFP_KERNEL);
183 if (new_crypt == NULL) 184 if (new_crypt == NULL)
184 return -ENOMEM; 185 return -ENOMEM;
185 memset(new_crypt, 0, sizeof(struct prism2_crypt_data)); 186 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
186 new_crypt->ops = hostap_get_crypto_ops("WEP"); 187 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
187 if (!new_crypt->ops) { 188 if (!new_crypt->ops) {
188 request_module("hostap_crypt_wep"); 189 request_module("ieee80211_crypt_wep");
189 new_crypt->ops = hostap_get_crypto_ops("WEP"); 190 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
190 } 191 }
191 if (new_crypt->ops) 192 if (new_crypt->ops)
192 new_crypt->priv = new_crypt->ops->init(i); 193 new_crypt->priv = new_crypt->ops->init(i);
@@ -251,7 +252,7 @@ static int prism2_ioctl_giwencode(struct net_device *dev,
251 local_info_t *local; 252 local_info_t *local;
252 int i, len; 253 int i, len;
253 u16 val; 254 u16 val;
254 struct prism2_crypt_data *crypt; 255 struct ieee80211_crypt_data *crypt;
255 256
256 iface = netdev_priv(dev); 257 iface = netdev_priv(dev);
257 local = iface->local; 258 local = iface->local;
@@ -3259,8 +3260,8 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev,
3259 local_info_t *local = iface->local; 3260 local_info_t *local = iface->local;
3260 struct iw_encode_ext *ext = (struct iw_encode_ext *) extra; 3261 struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
3261 int i, ret = 0; 3262 int i, ret = 0;
3262 struct hostap_crypto_ops *ops; 3263 struct ieee80211_crypto_ops *ops;
3263 struct prism2_crypt_data **crypt; 3264 struct ieee80211_crypt_data **crypt;
3264 void *sta_ptr; 3265 void *sta_ptr;
3265 u8 *addr; 3266 u8 *addr;
3266 const char *alg, *module; 3267 const char *alg, *module;
@@ -3308,15 +3309,15 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev,
3308 switch (ext->alg) { 3309 switch (ext->alg) {
3309 case IW_ENCODE_ALG_WEP: 3310 case IW_ENCODE_ALG_WEP:
3310 alg = "WEP"; 3311 alg = "WEP";
3311 module = "hostap_crypt_wep"; 3312 module = "ieee80211_crypt_wep";
3312 break; 3313 break;
3313 case IW_ENCODE_ALG_TKIP: 3314 case IW_ENCODE_ALG_TKIP:
3314 alg = "TKIP"; 3315 alg = "TKIP";
3315 module = "hostap_crypt_tkip"; 3316 module = "ieee80211_crypt_tkip";
3316 break; 3317 break;
3317 case IW_ENCODE_ALG_CCMP: 3318 case IW_ENCODE_ALG_CCMP:
3318 alg = "CCMP"; 3319 alg = "CCMP";
3319 module = "hostap_crypt_ccmp"; 3320 module = "ieee80211_crypt_ccmp";
3320 break; 3321 break;
3321 default: 3322 default:
3322 printk(KERN_DEBUG "%s: unsupported algorithm %d\n", 3323 printk(KERN_DEBUG "%s: unsupported algorithm %d\n",
@@ -3325,10 +3326,10 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev,
3325 goto done; 3326 goto done;
3326 } 3327 }
3327 3328
3328 ops = hostap_get_crypto_ops(alg); 3329 ops = ieee80211_get_crypto_ops(alg);
3329 if (ops == NULL) { 3330 if (ops == NULL) {
3330 request_module(module); 3331 request_module(module);
3331 ops = hostap_get_crypto_ops(alg); 3332 ops = ieee80211_get_crypto_ops(alg);
3332 } 3333 }
3333 if (ops == NULL) { 3334 if (ops == NULL) {
3334 printk(KERN_DEBUG "%s: unknown crypto alg '%s'\n", 3335 printk(KERN_DEBUG "%s: unknown crypto alg '%s'\n",
@@ -3347,17 +3348,18 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev,
3347 } 3348 }
3348 3349
3349 if (*crypt == NULL || (*crypt)->ops != ops) { 3350 if (*crypt == NULL || (*crypt)->ops != ops) {
3350 struct prism2_crypt_data *new_crypt; 3351 struct ieee80211_crypt_data *new_crypt;
3351 3352
3352 prism2_crypt_delayed_deinit(local, crypt); 3353 prism2_crypt_delayed_deinit(local, crypt);
3353 3354
3354 new_crypt = (struct prism2_crypt_data *) 3355 new_crypt = (struct ieee80211_crypt_data *)
3355 kmalloc(sizeof(struct prism2_crypt_data), GFP_KERNEL); 3356 kmalloc(sizeof(struct ieee80211_crypt_data),
3357 GFP_KERNEL);
3356 if (new_crypt == NULL) { 3358 if (new_crypt == NULL) {
3357 ret = -ENOMEM; 3359 ret = -ENOMEM;
3358 goto done; 3360 goto done;
3359 } 3361 }
3360 memset(new_crypt, 0, sizeof(struct prism2_crypt_data)); 3362 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
3361 new_crypt->ops = ops; 3363 new_crypt->ops = ops;
3362 new_crypt->priv = new_crypt->ops->init(i); 3364 new_crypt->priv = new_crypt->ops->init(i);
3363 if (new_crypt->priv == NULL) { 3365 if (new_crypt->priv == NULL) {
@@ -3436,7 +3438,7 @@ static int prism2_ioctl_giwencodeext(struct net_device *dev,
3436{ 3438{
3437 struct hostap_interface *iface = dev->priv; 3439 struct hostap_interface *iface = dev->priv;
3438 local_info_t *local = iface->local; 3440 local_info_t *local = iface->local;
3439 struct prism2_crypt_data **crypt; 3441 struct ieee80211_crypt_data **crypt;
3440 void *sta_ptr; 3442 void *sta_ptr;
3441 int max_key_len, i; 3443 int max_key_len, i;
3442 struct iw_encode_ext *ext = (struct iw_encode_ext *) extra; 3444 struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
@@ -3505,8 +3507,8 @@ static int prism2_ioctl_set_encryption(local_info_t *local,
3505 int param_len) 3507 int param_len)
3506{ 3508{
3507 int ret = 0; 3509 int ret = 0;
3508 struct hostap_crypto_ops *ops; 3510 struct ieee80211_crypto_ops *ops;
3509 struct prism2_crypt_data **crypt; 3511 struct ieee80211_crypt_data **crypt;
3510 void *sta_ptr; 3512 void *sta_ptr;
3511 3513
3512 param->u.crypt.err = 0; 3514 param->u.crypt.err = 0;
@@ -3544,16 +3546,16 @@ static int prism2_ioctl_set_encryption(local_info_t *local,
3544 goto done; 3546 goto done;
3545 } 3547 }
3546 3548
3547 ops = hostap_get_crypto_ops(param->u.crypt.alg); 3549 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3548 if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) { 3550 if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
3549 request_module("hostap_crypt_wep"); 3551 request_module("ieee80211_crypt_wep");
3550 ops = hostap_get_crypto_ops(param->u.crypt.alg); 3552 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3551 } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) { 3553 } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) {
3552 request_module("hostap_crypt_tkip"); 3554 request_module("ieee80211_crypt_tkip");
3553 ops = hostap_get_crypto_ops(param->u.crypt.alg); 3555 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3554 } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) { 3556 } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) {
3555 request_module("hostap_crypt_ccmp"); 3557 request_module("ieee80211_crypt_ccmp");
3556 ops = hostap_get_crypto_ops(param->u.crypt.alg); 3558 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3557 } 3559 }
3558 if (ops == NULL) { 3560 if (ops == NULL) {
3559 printk(KERN_DEBUG "%s: unknown crypto alg '%s'\n", 3561 printk(KERN_DEBUG "%s: unknown crypto alg '%s'\n",
@@ -3568,17 +3570,18 @@ static int prism2_ioctl_set_encryption(local_info_t *local,
3568 local->host_decrypt = local->host_encrypt = 1; 3570 local->host_decrypt = local->host_encrypt = 1;
3569 3571
3570 if (*crypt == NULL || (*crypt)->ops != ops) { 3572 if (*crypt == NULL || (*crypt)->ops != ops) {
3571 struct prism2_crypt_data *new_crypt; 3573 struct ieee80211_crypt_data *new_crypt;
3572 3574
3573 prism2_crypt_delayed_deinit(local, crypt); 3575 prism2_crypt_delayed_deinit(local, crypt);
3574 3576
3575 new_crypt = (struct prism2_crypt_data *) 3577 new_crypt = (struct ieee80211_crypt_data *)
3576 kmalloc(sizeof(struct prism2_crypt_data), GFP_KERNEL); 3578 kmalloc(sizeof(struct ieee80211_crypt_data),
3579 GFP_KERNEL);
3577 if (new_crypt == NULL) { 3580 if (new_crypt == NULL) {
3578 ret = -ENOMEM; 3581 ret = -ENOMEM;
3579 goto done; 3582 goto done;
3580 } 3583 }
3581 memset(new_crypt, 0, sizeof(struct prism2_crypt_data)); 3584 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
3582 new_crypt->ops = ops; 3585 new_crypt->ops = ops;
3583 new_crypt->priv = new_crypt->ops->init(param->u.crypt.idx); 3586 new_crypt->priv = new_crypt->ops->init(param->u.crypt.idx);
3584 if (new_crypt->priv == NULL) { 3587 if (new_crypt->priv == NULL) {
@@ -3642,7 +3645,7 @@ static int prism2_ioctl_get_encryption(local_info_t *local,
3642 struct prism2_hostapd_param *param, 3645 struct prism2_hostapd_param *param,
3643 int param_len) 3646 int param_len)
3644{ 3647{
3645 struct prism2_crypt_data **crypt; 3648 struct ieee80211_crypt_data **crypt;
3646 void *sta_ptr; 3649 void *sta_ptr;
3647 int max_key_len; 3650 int max_key_len;
3648 3651
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h
index f215a22e8fee..a632d45f334d 100644
--- a/drivers/net/wireless/hostap/hostap_wlan.h
+++ b/drivers/net/wireless/hostap/hostap_wlan.h
@@ -2,7 +2,6 @@
2#define HOSTAP_WLAN_H 2#define HOSTAP_WLAN_H
3 3
4#include "hostap_config.h" 4#include "hostap_config.h"
5#include "hostap_crypt.h"
6#include "hostap_common.h" 5#include "hostap_common.h"
7 6
8#define MAX_PARM_DEVICES 8 7#define MAX_PARM_DEVICES 8
@@ -534,13 +533,6 @@ struct prism2_frag_entry {
534}; 533};
535 534
536 535
537struct prism2_crypt_data {
538 struct list_head list; /* delayed deletion list */
539 struct hostap_crypto_ops *ops;
540 void *priv;
541 atomic_t refcnt;
542};
543
544struct hostap_cmd_queue { 536struct hostap_cmd_queue {
545 struct list_head list; 537 struct list_head list;
546 wait_queue_head_t compl; 538 wait_queue_head_t compl;
@@ -765,7 +757,7 @@ struct local_info {
765 757
766#define WEP_KEYS 4 758#define WEP_KEYS 4
767#define WEP_KEY_LEN 13 759#define WEP_KEY_LEN 13
768 struct prism2_crypt_data *crypt[WEP_KEYS]; 760 struct ieee80211_crypt_data *crypt[WEP_KEYS];
769 int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */ 761 int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */
770 struct timer_list crypt_deinit_timer; 762 struct timer_list crypt_deinit_timer;
771 struct list_head crypt_deinit_list; 763 struct list_head crypt_deinit_list;