diff options
author | John W. Linville <linville@tuxdriver.com> | 2008-10-29 11:35:05 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-11-21 11:08:17 -0500 |
commit | 274bfb8dc5ffa16cb073801bebe76ab7f4e2e73d (patch) | |
tree | 04cd3f6a062496911b56737daa6a0858b769ccd6 /net | |
parent | dfe1bafdbac1c7b48b636fb7ace799e78170e0d6 (diff) |
lib80211: absorb crypto bits from net/ieee80211
These bits are shared already between ipw2x00 and hostap, and could
probably be shared both more cleanly and with other drivers. This
commit simply relocates the code to lib80211 and adjusts the drivers
appropriately.
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/ieee80211/Kconfig | 15 | ||||
-rw-r--r-- | net/ieee80211/Makefile | 4 | ||||
-rw-r--r-- | net/ieee80211/ieee80211_crypt.c | 206 | ||||
-rw-r--r-- | net/ieee80211/ieee80211_module.c | 23 | ||||
-rw-r--r-- | net/ieee80211/ieee80211_rx.c | 8 | ||||
-rw-r--r-- | net/ieee80211/ieee80211_tx.c | 7 | ||||
-rw-r--r-- | net/ieee80211/ieee80211_wx.c | 68 | ||||
-rw-r--r-- | net/wireless/Kconfig | 9 | ||||
-rw-r--r-- | net/wireless/Makefile | 3 | ||||
-rw-r--r-- | net/wireless/lib80211.c | 191 | ||||
-rw-r--r-- | net/wireless/lib80211_crypt_ccmp.c (renamed from net/ieee80211/ieee80211_crypt_ccmp.c) | 118 | ||||
-rw-r--r-- | net/wireless/lib80211_crypt_tkip.c (renamed from net/ieee80211/ieee80211_crypt_tkip.c) | 154 | ||||
-rw-r--r-- | net/wireless/lib80211_crypt_wep.c (renamed from net/ieee80211/ieee80211_crypt_wep.c) | 79 |
13 files changed, 433 insertions, 452 deletions
diff --git a/net/ieee80211/Kconfig b/net/ieee80211/Kconfig index d2282bb2e4f1..46f24f4c9dc7 100644 --- a/net/ieee80211/Kconfig +++ b/net/ieee80211/Kconfig | |||
@@ -8,10 +8,10 @@ config IEEE80211 | |||
8 | select CRYPTO_MICHAEL_MIC | 8 | select CRYPTO_MICHAEL_MIC |
9 | select CRYPTO_ECB | 9 | select CRYPTO_ECB |
10 | select CRC32 | 10 | select CRC32 |
11 | select IEEE80211_CRYPT_WEP | ||
12 | select IEEE80211_CRYPT_TKIP | ||
13 | select IEEE80211_CRYPT_CCMP | ||
14 | select LIB80211 | 11 | select LIB80211 |
12 | select LIB80211_CRYPT_WEP | ||
13 | select LIB80211_CRYPT_TKIP | ||
14 | select LIB80211_CRYPT_CCMP | ||
15 | ---help--- | 15 | ---help--- |
16 | This option enables the hardware independent IEEE 802.11 | 16 | This option enables the hardware independent IEEE 802.11 |
17 | networking stack. This component is deprecated in favor of the | 17 | networking stack. This component is deprecated in favor of the |
@@ -39,12 +39,3 @@ config IEEE80211_DEBUG | |||
39 | 39 | ||
40 | If you are not trying to debug or develop the ieee80211 | 40 | If you are not trying to debug or develop the ieee80211 |
41 | subsystem, you most likely want to say N here. | 41 | subsystem, you most likely want to say N here. |
42 | |||
43 | config IEEE80211_CRYPT_WEP | ||
44 | tristate | ||
45 | |||
46 | config IEEE80211_CRYPT_CCMP | ||
47 | tristate | ||
48 | |||
49 | config IEEE80211_CRYPT_TKIP | ||
50 | tristate | ||
diff --git a/net/ieee80211/Makefile b/net/ieee80211/Makefile index f988417121da..158963ff18d2 100644 --- a/net/ieee80211/Makefile +++ b/net/ieee80211/Makefile | |||
@@ -1,8 +1,4 @@ | |||
1 | obj-$(CONFIG_IEEE80211) += ieee80211.o | 1 | obj-$(CONFIG_IEEE80211) += ieee80211.o |
2 | obj-$(CONFIG_IEEE80211) += ieee80211_crypt.o | ||
3 | obj-$(CONFIG_IEEE80211_CRYPT_WEP) += ieee80211_crypt_wep.o | ||
4 | obj-$(CONFIG_IEEE80211_CRYPT_CCMP) += ieee80211_crypt_ccmp.o | ||
5 | obj-$(CONFIG_IEEE80211_CRYPT_TKIP) += ieee80211_crypt_tkip.o | ||
6 | ieee80211-objs := \ | 2 | ieee80211-objs := \ |
7 | ieee80211_module.o \ | 3 | ieee80211_module.o \ |
8 | ieee80211_tx.o \ | 4 | ieee80211_tx.o \ |
diff --git a/net/ieee80211/ieee80211_crypt.c b/net/ieee80211/ieee80211_crypt.c deleted file mode 100644 index df5592c9339f..000000000000 --- a/net/ieee80211/ieee80211_crypt.c +++ /dev/null | |||
@@ -1,206 +0,0 @@ | |||
1 | /* | ||
2 | * Host AP crypto routines | ||
3 | * | ||
4 | * Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi> | ||
5 | * Portions Copyright (C) 2004, Intel Corporation <jketreno@linux.intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. See README and COPYING for | ||
10 | * more details. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/errno.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/string.h> | ||
19 | #include <net/ieee80211.h> | ||
20 | |||
21 | MODULE_AUTHOR("Jouni Malinen"); | ||
22 | MODULE_DESCRIPTION("HostAP crypto"); | ||
23 | MODULE_LICENSE("GPL"); | ||
24 | |||
25 | struct ieee80211_crypto_alg { | ||
26 | struct list_head list; | ||
27 | struct ieee80211_crypto_ops *ops; | ||
28 | }; | ||
29 | |||
30 | static LIST_HEAD(ieee80211_crypto_algs); | ||
31 | static DEFINE_SPINLOCK(ieee80211_crypto_lock); | ||
32 | |||
33 | void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force) | ||
34 | { | ||
35 | struct ieee80211_crypt_data *entry, *next; | ||
36 | unsigned long flags; | ||
37 | |||
38 | spin_lock_irqsave(&ieee->lock, flags); | ||
39 | list_for_each_entry_safe(entry, next, &ieee->crypt_deinit_list, list) { | ||
40 | if (atomic_read(&entry->refcnt) != 0 && !force) | ||
41 | continue; | ||
42 | |||
43 | list_del(&entry->list); | ||
44 | |||
45 | if (entry->ops) { | ||
46 | entry->ops->deinit(entry->priv); | ||
47 | module_put(entry->ops->owner); | ||
48 | } | ||
49 | kfree(entry); | ||
50 | } | ||
51 | spin_unlock_irqrestore(&ieee->lock, flags); | ||
52 | } | ||
53 | |||
54 | /* After this, crypt_deinit_list won't accept new members */ | ||
55 | void ieee80211_crypt_quiescing(struct ieee80211_device *ieee) | ||
56 | { | ||
57 | unsigned long flags; | ||
58 | |||
59 | spin_lock_irqsave(&ieee->lock, flags); | ||
60 | ieee->crypt_quiesced = 1; | ||
61 | spin_unlock_irqrestore(&ieee->lock, flags); | ||
62 | } | ||
63 | |||
64 | void ieee80211_crypt_deinit_handler(unsigned long data) | ||
65 | { | ||
66 | struct ieee80211_device *ieee = (struct ieee80211_device *)data; | ||
67 | unsigned long flags; | ||
68 | |||
69 | ieee80211_crypt_deinit_entries(ieee, 0); | ||
70 | |||
71 | spin_lock_irqsave(&ieee->lock, flags); | ||
72 | if (!list_empty(&ieee->crypt_deinit_list) && !ieee->crypt_quiesced) { | ||
73 | printk(KERN_DEBUG "%s: entries remaining in delayed crypt " | ||
74 | "deletion list\n", ieee->dev->name); | ||
75 | ieee->crypt_deinit_timer.expires = jiffies + HZ; | ||
76 | add_timer(&ieee->crypt_deinit_timer); | ||
77 | } | ||
78 | spin_unlock_irqrestore(&ieee->lock, flags); | ||
79 | } | ||
80 | |||
81 | void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee, | ||
82 | struct ieee80211_crypt_data **crypt) | ||
83 | { | ||
84 | struct ieee80211_crypt_data *tmp; | ||
85 | unsigned long flags; | ||
86 | |||
87 | if (*crypt == NULL) | ||
88 | return; | ||
89 | |||
90 | tmp = *crypt; | ||
91 | *crypt = NULL; | ||
92 | |||
93 | /* must not run ops->deinit() while there may be pending encrypt or | ||
94 | * decrypt operations. Use a list of delayed deinits to avoid needing | ||
95 | * locking. */ | ||
96 | |||
97 | spin_lock_irqsave(&ieee->lock, flags); | ||
98 | if (!ieee->crypt_quiesced) { | ||
99 | list_add(&tmp->list, &ieee->crypt_deinit_list); | ||
100 | if (!timer_pending(&ieee->crypt_deinit_timer)) { | ||
101 | ieee->crypt_deinit_timer.expires = jiffies + HZ; | ||
102 | add_timer(&ieee->crypt_deinit_timer); | ||
103 | } | ||
104 | } | ||
105 | spin_unlock_irqrestore(&ieee->lock, flags); | ||
106 | } | ||
107 | |||
108 | int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops) | ||
109 | { | ||
110 | unsigned long flags; | ||
111 | struct ieee80211_crypto_alg *alg; | ||
112 | |||
113 | alg = kzalloc(sizeof(*alg), GFP_KERNEL); | ||
114 | if (alg == NULL) | ||
115 | return -ENOMEM; | ||
116 | |||
117 | alg->ops = ops; | ||
118 | |||
119 | spin_lock_irqsave(&ieee80211_crypto_lock, flags); | ||
120 | list_add(&alg->list, &ieee80211_crypto_algs); | ||
121 | spin_unlock_irqrestore(&ieee80211_crypto_lock, flags); | ||
122 | |||
123 | printk(KERN_DEBUG "ieee80211_crypt: registered algorithm '%s'\n", | ||
124 | ops->name); | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops) | ||
130 | { | ||
131 | struct ieee80211_crypto_alg *alg; | ||
132 | unsigned long flags; | ||
133 | |||
134 | spin_lock_irqsave(&ieee80211_crypto_lock, flags); | ||
135 | list_for_each_entry(alg, &ieee80211_crypto_algs, list) { | ||
136 | if (alg->ops == ops) | ||
137 | goto found; | ||
138 | } | ||
139 | spin_unlock_irqrestore(&ieee80211_crypto_lock, flags); | ||
140 | return -EINVAL; | ||
141 | |||
142 | found: | ||
143 | printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm " | ||
144 | "'%s'\n", ops->name); | ||
145 | list_del(&alg->list); | ||
146 | spin_unlock_irqrestore(&ieee80211_crypto_lock, flags); | ||
147 | kfree(alg); | ||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name) | ||
152 | { | ||
153 | struct ieee80211_crypto_alg *alg; | ||
154 | unsigned long flags; | ||
155 | |||
156 | spin_lock_irqsave(&ieee80211_crypto_lock, flags); | ||
157 | list_for_each_entry(alg, &ieee80211_crypto_algs, list) { | ||
158 | if (strcmp(alg->ops->name, name) == 0) | ||
159 | goto found; | ||
160 | } | ||
161 | spin_unlock_irqrestore(&ieee80211_crypto_lock, flags); | ||
162 | return NULL; | ||
163 | |||
164 | found: | ||
165 | spin_unlock_irqrestore(&ieee80211_crypto_lock, flags); | ||
166 | return alg->ops; | ||
167 | } | ||
168 | |||
169 | static void *ieee80211_crypt_null_init(int keyidx) | ||
170 | { | ||
171 | return (void *)1; | ||
172 | } | ||
173 | |||
174 | static void ieee80211_crypt_null_deinit(void *priv) | ||
175 | { | ||
176 | } | ||
177 | |||
178 | static struct ieee80211_crypto_ops ieee80211_crypt_null = { | ||
179 | .name = "NULL", | ||
180 | .init = ieee80211_crypt_null_init, | ||
181 | .deinit = ieee80211_crypt_null_deinit, | ||
182 | .owner = THIS_MODULE, | ||
183 | }; | ||
184 | |||
185 | static int __init ieee80211_crypto_init(void) | ||
186 | { | ||
187 | return ieee80211_register_crypto_ops(&ieee80211_crypt_null); | ||
188 | } | ||
189 | |||
190 | static void __exit ieee80211_crypto_deinit(void) | ||
191 | { | ||
192 | ieee80211_unregister_crypto_ops(&ieee80211_crypt_null); | ||
193 | BUG_ON(!list_empty(&ieee80211_crypto_algs)); | ||
194 | } | ||
195 | |||
196 | EXPORT_SYMBOL(ieee80211_crypt_deinit_entries); | ||
197 | EXPORT_SYMBOL(ieee80211_crypt_deinit_handler); | ||
198 | EXPORT_SYMBOL(ieee80211_crypt_delayed_deinit); | ||
199 | EXPORT_SYMBOL(ieee80211_crypt_quiescing); | ||
200 | |||
201 | EXPORT_SYMBOL(ieee80211_register_crypto_ops); | ||
202 | EXPORT_SYMBOL(ieee80211_unregister_crypto_ops); | ||
203 | EXPORT_SYMBOL(ieee80211_get_crypto_ops); | ||
204 | |||
205 | module_init(ieee80211_crypto_init); | ||
206 | module_exit(ieee80211_crypto_deinit); | ||
diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c index d34d4e79b6f7..cf21f0bd8569 100644 --- a/net/ieee80211/ieee80211_module.c +++ b/net/ieee80211/ieee80211_module.c | |||
@@ -180,13 +180,16 @@ struct net_device *alloc_ieee80211(int sizeof_priv) | |||
180 | ieee->host_open_frag = 1; | 180 | ieee->host_open_frag = 1; |
181 | ieee->ieee802_1x = 1; /* Default to supporting 802.1x */ | 181 | ieee->ieee802_1x = 1; /* Default to supporting 802.1x */ |
182 | 182 | ||
183 | INIT_LIST_HEAD(&ieee->crypt_deinit_list); | ||
184 | setup_timer(&ieee->crypt_deinit_timer, ieee80211_crypt_deinit_handler, | ||
185 | (unsigned long)ieee); | ||
186 | ieee->crypt_quiesced = 0; | ||
187 | |||
188 | spin_lock_init(&ieee->lock); | 183 | spin_lock_init(&ieee->lock); |
189 | 184 | ||
185 | ieee->crypt_info.name = dev->name; | ||
186 | ieee->crypt_info.lock = &ieee->lock; | ||
187 | INIT_LIST_HEAD(&ieee->crypt_info.crypt_deinit_list); | ||
188 | setup_timer(&ieee->crypt_info.crypt_deinit_timer, | ||
189 | lib80211_crypt_deinit_handler, | ||
190 | (unsigned long)&ieee->crypt_info); | ||
191 | ieee->crypt_info.crypt_quiesced = 0; | ||
192 | |||
190 | ieee->wpa_enabled = 0; | 193 | ieee->wpa_enabled = 0; |
191 | ieee->drop_unencrypted = 0; | 194 | ieee->drop_unencrypted = 0; |
192 | ieee->privacy_invoked = 0; | 195 | ieee->privacy_invoked = 0; |
@@ -205,19 +208,19 @@ void free_ieee80211(struct net_device *dev) | |||
205 | 208 | ||
206 | int i; | 209 | int i; |
207 | 210 | ||
208 | ieee80211_crypt_quiescing(ieee); | 211 | lib80211_crypt_quiescing(&ieee->crypt_info); |
209 | del_timer_sync(&ieee->crypt_deinit_timer); | 212 | del_timer_sync(&ieee->crypt_info.crypt_deinit_timer); |
210 | ieee80211_crypt_deinit_entries(ieee, 1); | 213 | lib80211_crypt_deinit_entries(&ieee->crypt_info, 1); |
211 | 214 | ||
212 | for (i = 0; i < WEP_KEYS; i++) { | 215 | for (i = 0; i < WEP_KEYS; i++) { |
213 | struct ieee80211_crypt_data *crypt = ieee->crypt[i]; | 216 | struct lib80211_crypt_data *crypt = ieee->crypt_info.crypt[i]; |
214 | if (crypt) { | 217 | if (crypt) { |
215 | if (crypt->ops) { | 218 | if (crypt->ops) { |
216 | crypt->ops->deinit(crypt->priv); | 219 | crypt->ops->deinit(crypt->priv); |
217 | module_put(crypt->ops->owner); | 220 | module_put(crypt->ops->owner); |
218 | } | 221 | } |
219 | kfree(crypt); | 222 | kfree(crypt); |
220 | ieee->crypt[i] = NULL; | 223 | ieee->crypt_info.crypt[i] = NULL; |
221 | } | 224 | } |
222 | } | 225 | } |
223 | 226 | ||
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index 3dd58b594f6a..9c67dfae4320 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c | |||
@@ -268,7 +268,7 @@ static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee, | |||
268 | /* Called only as a tasklet (software IRQ), by ieee80211_rx */ | 268 | /* Called only as a tasklet (software IRQ), by ieee80211_rx */ |
269 | static int | 269 | static int |
270 | ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb, | 270 | ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb, |
271 | struct ieee80211_crypt_data *crypt) | 271 | struct lib80211_crypt_data *crypt) |
272 | { | 272 | { |
273 | struct ieee80211_hdr_3addr *hdr; | 273 | struct ieee80211_hdr_3addr *hdr; |
274 | int res, hdrlen; | 274 | int res, hdrlen; |
@@ -300,7 +300,7 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb, | |||
300 | static int | 300 | static int |
301 | ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee, | 301 | ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee, |
302 | struct sk_buff *skb, int keyidx, | 302 | struct sk_buff *skb, int keyidx, |
303 | struct ieee80211_crypt_data *crypt) | 303 | struct lib80211_crypt_data *crypt) |
304 | { | 304 | { |
305 | struct ieee80211_hdr_3addr *hdr; | 305 | struct ieee80211_hdr_3addr *hdr; |
306 | int res, hdrlen; | 306 | int res, hdrlen; |
@@ -348,7 +348,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, | |||
348 | #endif | 348 | #endif |
349 | u8 dst[ETH_ALEN]; | 349 | u8 dst[ETH_ALEN]; |
350 | u8 src[ETH_ALEN]; | 350 | u8 src[ETH_ALEN]; |
351 | struct ieee80211_crypt_data *crypt = NULL; | 351 | struct lib80211_crypt_data *crypt = NULL; |
352 | int keyidx = 0; | 352 | int keyidx = 0; |
353 | int can_be_decrypted = 0; | 353 | int can_be_decrypted = 0; |
354 | 354 | ||
@@ -431,7 +431,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, | |||
431 | * is only allowed 2-bits of storage, no value of keyidx can | 431 | * is only allowed 2-bits of storage, no value of keyidx can |
432 | * be provided via above code that would result in keyidx | 432 | * be provided via above code that would result in keyidx |
433 | * being out of range */ | 433 | * being out of range */ |
434 | crypt = ieee->crypt[keyidx]; | 434 | crypt = ieee->crypt_info.crypt[keyidx]; |
435 | 435 | ||
436 | #ifdef NOT_YET | 436 | #ifdef NOT_YET |
437 | sta = NULL; | 437 | sta = NULL; |
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c index d996547f7a62..f78f57e8844a 100644 --- a/net/ieee80211/ieee80211_tx.c +++ b/net/ieee80211/ieee80211_tx.c | |||
@@ -152,7 +152,8 @@ static int ieee80211_copy_snap(u8 * data, __be16 h_proto) | |||
152 | static int ieee80211_encrypt_fragment(struct ieee80211_device *ieee, | 152 | static int ieee80211_encrypt_fragment(struct ieee80211_device *ieee, |
153 | struct sk_buff *frag, int hdr_len) | 153 | struct sk_buff *frag, int hdr_len) |
154 | { | 154 | { |
155 | struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx]; | 155 | struct lib80211_crypt_data *crypt = |
156 | ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx]; | ||
156 | int res; | 157 | int res; |
157 | 158 | ||
158 | if (crypt == NULL) | 159 | if (crypt == NULL) |
@@ -270,7 +271,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) | |||
270 | .qos_ctl = 0 | 271 | .qos_ctl = 0 |
271 | }; | 272 | }; |
272 | u8 dest[ETH_ALEN], src[ETH_ALEN]; | 273 | u8 dest[ETH_ALEN], src[ETH_ALEN]; |
273 | struct ieee80211_crypt_data *crypt; | 274 | struct lib80211_crypt_data *crypt; |
274 | int priority = skb->priority; | 275 | int priority = skb->priority; |
275 | int snapped = 0; | 276 | int snapped = 0; |
276 | 277 | ||
@@ -294,7 +295,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) | |||
294 | 295 | ||
295 | ether_type = ((struct ethhdr *)skb->data)->h_proto; | 296 | ether_type = ((struct ethhdr *)skb->data)->h_proto; |
296 | 297 | ||
297 | crypt = ieee->crypt[ieee->tx_keyidx]; | 298 | crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx]; |
298 | 299 | ||
299 | encrypt = !(ether_type == htons(ETH_P_PAE) && ieee->ieee802_1x) && | 300 | encrypt = !(ether_type == htons(ETH_P_PAE) && ieee->ieee802_1x) && |
300 | ieee->sec.encrypt; | 301 | ieee->sec.encrypt; |
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c index 7cc4e5ee3660..31ea3abfc327 100644 --- a/net/ieee80211/ieee80211_wx.c +++ b/net/ieee80211/ieee80211_wx.c | |||
@@ -307,7 +307,7 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee, | |||
307 | .flags = 0 | 307 | .flags = 0 |
308 | }; | 308 | }; |
309 | int i, key, key_provided, len; | 309 | int i, key, key_provided, len; |
310 | struct ieee80211_crypt_data **crypt; | 310 | struct lib80211_crypt_data **crypt; |
311 | int host_crypto = ieee->host_encrypt || ieee->host_decrypt || ieee->host_build_iv; | 311 | int host_crypto = ieee->host_encrypt || ieee->host_decrypt || ieee->host_build_iv; |
312 | DECLARE_SSID_BUF(ssid); | 312 | DECLARE_SSID_BUF(ssid); |
313 | 313 | ||
@@ -321,30 +321,30 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee, | |||
321 | key_provided = 1; | 321 | key_provided = 1; |
322 | } else { | 322 | } else { |
323 | key_provided = 0; | 323 | key_provided = 0; |
324 | key = ieee->tx_keyidx; | 324 | key = ieee->crypt_info.tx_keyidx; |
325 | } | 325 | } |
326 | 326 | ||
327 | IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ? | 327 | IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ? |
328 | "provided" : "default"); | 328 | "provided" : "default"); |
329 | 329 | ||
330 | crypt = &ieee->crypt[key]; | 330 | crypt = &ieee->crypt_info.crypt[key]; |
331 | 331 | ||
332 | if (erq->flags & IW_ENCODE_DISABLED) { | 332 | if (erq->flags & IW_ENCODE_DISABLED) { |
333 | if (key_provided && *crypt) { | 333 | if (key_provided && *crypt) { |
334 | IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n", | 334 | IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n", |
335 | key); | 335 | key); |
336 | ieee80211_crypt_delayed_deinit(ieee, crypt); | 336 | lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt); |
337 | } else | 337 | } else |
338 | IEEE80211_DEBUG_WX("Disabling encryption.\n"); | 338 | IEEE80211_DEBUG_WX("Disabling encryption.\n"); |
339 | 339 | ||
340 | /* Check all the keys to see if any are still configured, | 340 | /* Check all the keys to see if any are still configured, |
341 | * and if no key index was provided, de-init them all */ | 341 | * and if no key index was provided, de-init them all */ |
342 | for (i = 0; i < WEP_KEYS; i++) { | 342 | for (i = 0; i < WEP_KEYS; i++) { |
343 | if (ieee->crypt[i] != NULL) { | 343 | if (ieee->crypt_info.crypt[i] != NULL) { |
344 | if (key_provided) | 344 | if (key_provided) |
345 | break; | 345 | break; |
346 | ieee80211_crypt_delayed_deinit(ieee, | 346 | lib80211_crypt_delayed_deinit(&ieee->crypt_info, |
347 | &ieee->crypt[i]); | 347 | &ieee->crypt_info.crypt[i]); |
348 | } | 348 | } |
349 | } | 349 | } |
350 | 350 | ||
@@ -366,21 +366,21 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee, | |||
366 | strcmp((*crypt)->ops->name, "WEP") != 0) { | 366 | strcmp((*crypt)->ops->name, "WEP") != 0) { |
367 | /* changing to use WEP; deinit previously used algorithm | 367 | /* changing to use WEP; deinit previously used algorithm |
368 | * on this key */ | 368 | * on this key */ |
369 | ieee80211_crypt_delayed_deinit(ieee, crypt); | 369 | lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt); |
370 | } | 370 | } |
371 | 371 | ||
372 | if (*crypt == NULL && host_crypto) { | 372 | if (*crypt == NULL && host_crypto) { |
373 | struct ieee80211_crypt_data *new_crypt; | 373 | struct lib80211_crypt_data *new_crypt; |
374 | 374 | ||
375 | /* take WEP into use */ | 375 | /* take WEP into use */ |
376 | new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data), | 376 | new_crypt = kzalloc(sizeof(struct lib80211_crypt_data), |
377 | GFP_KERNEL); | 377 | GFP_KERNEL); |
378 | if (new_crypt == NULL) | 378 | if (new_crypt == NULL) |
379 | return -ENOMEM; | 379 | return -ENOMEM; |
380 | new_crypt->ops = ieee80211_get_crypto_ops("WEP"); | 380 | new_crypt->ops = lib80211_get_crypto_ops("WEP"); |
381 | if (!new_crypt->ops) { | 381 | if (!new_crypt->ops) { |
382 | request_module("ieee80211_crypt_wep"); | 382 | request_module("lib80211_crypt_wep"); |
383 | new_crypt->ops = ieee80211_get_crypto_ops("WEP"); | 383 | new_crypt->ops = lib80211_get_crypto_ops("WEP"); |
384 | } | 384 | } |
385 | 385 | ||
386 | if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) | 386 | if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) |
@@ -391,7 +391,7 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee, | |||
391 | new_crypt = NULL; | 391 | new_crypt = NULL; |
392 | 392 | ||
393 | printk(KERN_WARNING "%s: could not initialize WEP: " | 393 | printk(KERN_WARNING "%s: could not initialize WEP: " |
394 | "load module ieee80211_crypt_wep\n", dev->name); | 394 | "load module lib80211_crypt_wep\n", dev->name); |
395 | return -EOPNOTSUPP; | 395 | return -EOPNOTSUPP; |
396 | } | 396 | } |
397 | *crypt = new_crypt; | 397 | *crypt = new_crypt; |
@@ -440,7 +440,7 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee, | |||
440 | if (key_provided) { | 440 | if (key_provided) { |
441 | IEEE80211_DEBUG_WX("Setting key %d to default Tx " | 441 | IEEE80211_DEBUG_WX("Setting key %d to default Tx " |
442 | "key.\n", key); | 442 | "key.\n", key); |
443 | ieee->tx_keyidx = key; | 443 | ieee->crypt_info.tx_keyidx = key; |
444 | sec.active_key = key; | 444 | sec.active_key = key; |
445 | sec.flags |= SEC_ACTIVE_KEY; | 445 | sec.flags |= SEC_ACTIVE_KEY; |
446 | } | 446 | } |
@@ -485,7 +485,7 @@ int ieee80211_wx_get_encode(struct ieee80211_device *ieee, | |||
485 | { | 485 | { |
486 | struct iw_point *erq = &(wrqu->encoding); | 486 | struct iw_point *erq = &(wrqu->encoding); |
487 | int len, key; | 487 | int len, key; |
488 | struct ieee80211_crypt_data *crypt; | 488 | struct lib80211_crypt_data *crypt; |
489 | struct ieee80211_security *sec = &ieee->sec; | 489 | struct ieee80211_security *sec = &ieee->sec; |
490 | 490 | ||
491 | IEEE80211_DEBUG_WX("GET_ENCODE\n"); | 491 | IEEE80211_DEBUG_WX("GET_ENCODE\n"); |
@@ -496,9 +496,9 @@ int ieee80211_wx_get_encode(struct ieee80211_device *ieee, | |||
496 | return -EINVAL; | 496 | return -EINVAL; |
497 | key--; | 497 | key--; |
498 | } else | 498 | } else |
499 | key = ieee->tx_keyidx; | 499 | key = ieee->crypt_info.tx_keyidx; |
500 | 500 | ||
501 | crypt = ieee->crypt[key]; | 501 | crypt = ieee->crypt_info.crypt[key]; |
502 | erq->flags = key + 1; | 502 | erq->flags = key + 1; |
503 | 503 | ||
504 | if (!sec->enabled) { | 504 | if (!sec->enabled) { |
@@ -531,8 +531,8 @@ int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee, | |||
531 | int i, idx, ret = 0; | 531 | int i, idx, ret = 0; |
532 | int group_key = 0; | 532 | int group_key = 0; |
533 | const char *alg, *module; | 533 | const char *alg, *module; |
534 | struct ieee80211_crypto_ops *ops; | 534 | struct lib80211_crypto_ops *ops; |
535 | struct ieee80211_crypt_data **crypt; | 535 | struct lib80211_crypt_data **crypt; |
536 | 536 | ||
537 | struct ieee80211_security sec = { | 537 | struct ieee80211_security sec = { |
538 | .flags = 0, | 538 | .flags = 0, |
@@ -544,17 +544,17 @@ int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee, | |||
544 | return -EINVAL; | 544 | return -EINVAL; |
545 | idx--; | 545 | idx--; |
546 | } else | 546 | } else |
547 | idx = ieee->tx_keyidx; | 547 | idx = ieee->crypt_info.tx_keyidx; |
548 | 548 | ||
549 | if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { | 549 | if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { |
550 | crypt = &ieee->crypt[idx]; | 550 | crypt = &ieee->crypt_info.crypt[idx]; |
551 | group_key = 1; | 551 | group_key = 1; |
552 | } else { | 552 | } else { |
553 | /* some Cisco APs use idx>0 for unicast in dynamic WEP */ | 553 | /* some Cisco APs use idx>0 for unicast in dynamic WEP */ |
554 | if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP) | 554 | if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP) |
555 | return -EINVAL; | 555 | return -EINVAL; |
556 | if (ieee->iw_mode == IW_MODE_INFRA) | 556 | if (ieee->iw_mode == IW_MODE_INFRA) |
557 | crypt = &ieee->crypt[idx]; | 557 | crypt = &ieee->crypt_info.crypt[idx]; |
558 | else | 558 | else |
559 | return -EINVAL; | 559 | return -EINVAL; |
560 | } | 560 | } |
@@ -563,10 +563,10 @@ int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee, | |||
563 | if ((encoding->flags & IW_ENCODE_DISABLED) || | 563 | if ((encoding->flags & IW_ENCODE_DISABLED) || |
564 | ext->alg == IW_ENCODE_ALG_NONE) { | 564 | ext->alg == IW_ENCODE_ALG_NONE) { |
565 | if (*crypt) | 565 | if (*crypt) |
566 | ieee80211_crypt_delayed_deinit(ieee, crypt); | 566 | lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt); |
567 | 567 | ||
568 | for (i = 0; i < WEP_KEYS; i++) | 568 | for (i = 0; i < WEP_KEYS; i++) |
569 | if (ieee->crypt[i] != NULL) | 569 | if (ieee->crypt_info.crypt[i] != NULL) |
570 | break; | 570 | break; |
571 | 571 | ||
572 | if (i == WEP_KEYS) { | 572 | if (i == WEP_KEYS) { |
@@ -589,15 +589,15 @@ int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee, | |||
589 | switch (ext->alg) { | 589 | switch (ext->alg) { |
590 | case IW_ENCODE_ALG_WEP: | 590 | case IW_ENCODE_ALG_WEP: |
591 | alg = "WEP"; | 591 | alg = "WEP"; |
592 | module = "ieee80211_crypt_wep"; | 592 | module = "lib80211_crypt_wep"; |
593 | break; | 593 | break; |
594 | case IW_ENCODE_ALG_TKIP: | 594 | case IW_ENCODE_ALG_TKIP: |
595 | alg = "TKIP"; | 595 | alg = "TKIP"; |
596 | module = "ieee80211_crypt_tkip"; | 596 | module = "lib80211_crypt_tkip"; |
597 | break; | 597 | break; |
598 | case IW_ENCODE_ALG_CCMP: | 598 | case IW_ENCODE_ALG_CCMP: |
599 | alg = "CCMP"; | 599 | alg = "CCMP"; |
600 | module = "ieee80211_crypt_ccmp"; | 600 | module = "lib80211_crypt_ccmp"; |
601 | break; | 601 | break; |
602 | default: | 602 | default: |
603 | IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n", | 603 | IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n", |
@@ -606,10 +606,10 @@ int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee, | |||
606 | goto done; | 606 | goto done; |
607 | } | 607 | } |
608 | 608 | ||
609 | ops = ieee80211_get_crypto_ops(alg); | 609 | ops = lib80211_get_crypto_ops(alg); |
610 | if (ops == NULL) { | 610 | if (ops == NULL) { |
611 | request_module(module); | 611 | request_module(module); |
612 | ops = ieee80211_get_crypto_ops(alg); | 612 | ops = lib80211_get_crypto_ops(alg); |
613 | } | 613 | } |
614 | if (ops == NULL) { | 614 | if (ops == NULL) { |
615 | IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n", | 615 | IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n", |
@@ -619,9 +619,9 @@ int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee, | |||
619 | } | 619 | } |
620 | 620 | ||
621 | if (*crypt == NULL || (*crypt)->ops != ops) { | 621 | if (*crypt == NULL || (*crypt)->ops != ops) { |
622 | struct ieee80211_crypt_data *new_crypt; | 622 | struct lib80211_crypt_data *new_crypt; |
623 | 623 | ||
624 | ieee80211_crypt_delayed_deinit(ieee, crypt); | 624 | lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt); |
625 | 625 | ||
626 | new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL); | 626 | new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL); |
627 | if (new_crypt == NULL) { | 627 | if (new_crypt == NULL) { |
@@ -649,7 +649,7 @@ int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee, | |||
649 | 649 | ||
650 | skip_host_crypt: | 650 | skip_host_crypt: |
651 | if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { | 651 | if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { |
652 | ieee->tx_keyidx = idx; | 652 | ieee->crypt_info.tx_keyidx = idx; |
653 | sec.active_key = idx; | 653 | sec.active_key = idx; |
654 | sec.flags |= SEC_ACTIVE_KEY; | 654 | sec.flags |= SEC_ACTIVE_KEY; |
655 | } | 655 | } |
@@ -715,7 +715,7 @@ int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee, | |||
715 | return -EINVAL; | 715 | return -EINVAL; |
716 | idx--; | 716 | idx--; |
717 | } else | 717 | } else |
718 | idx = ieee->tx_keyidx; | 718 | idx = ieee->crypt_info.tx_keyidx; |
719 | 719 | ||
720 | if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) && | 720 | if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) && |
721 | ext->alg != IW_ENCODE_ALG_WEP) | 721 | ext->alg != IW_ENCODE_ALG_WEP) |
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index ae7f2262dfb5..f7c64dbe86cc 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig | |||
@@ -82,3 +82,12 @@ config LIB80211 | |||
82 | 82 | ||
83 | Drivers should select this themselves if needed. Say Y if | 83 | Drivers should select this themselves if needed. Say Y if |
84 | you want this built into your kernel. | 84 | you want this built into your kernel. |
85 | |||
86 | config LIB80211_CRYPT_WEP | ||
87 | tristate | ||
88 | |||
89 | config LIB80211_CRYPT_CCMP | ||
90 | tristate | ||
91 | |||
92 | config LIB80211_CRYPT_TKIP | ||
93 | tristate | ||
diff --git a/net/wireless/Makefile b/net/wireless/Makefile index d2d848d445f2..cc547edb111f 100644 --- a/net/wireless/Makefile +++ b/net/wireless/Makefile | |||
@@ -1,6 +1,9 @@ | |||
1 | obj-$(CONFIG_WIRELESS_EXT) += wext.o | 1 | obj-$(CONFIG_WIRELESS_EXT) += wext.o |
2 | obj-$(CONFIG_CFG80211) += cfg80211.o | 2 | obj-$(CONFIG_CFG80211) += cfg80211.o |
3 | obj-$(CONFIG_LIB80211) += lib80211.o | 3 | obj-$(CONFIG_LIB80211) += lib80211.o |
4 | obj-$(CONFIG_LIB80211_CRYPT_WEP) += lib80211_crypt_wep.o | ||
5 | obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o | ||
6 | obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o | ||
4 | 7 | ||
5 | cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o | 8 | cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o |
6 | cfg80211-$(CONFIG_NL80211) += nl80211.o | 9 | cfg80211-$(CONFIG_NL80211) += nl80211.o |
diff --git a/net/wireless/lib80211.c b/net/wireless/lib80211.c index e71f7d085621..d681721f4acb 100644 --- a/net/wireless/lib80211.c +++ b/net/wireless/lib80211.c | |||
@@ -3,11 +3,23 @@ | |||
3 | * | 3 | * |
4 | * Copyright(c) 2008 John W. Linville <linville@tuxdriver.com> | 4 | * Copyright(c) 2008 John W. Linville <linville@tuxdriver.com> |
5 | * | 5 | * |
6 | * Portions copied from old ieee80211 component, w/ original copyright | ||
7 | * notices below: | ||
8 | * | ||
9 | * Host AP crypto routines | ||
10 | * | ||
11 | * Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi> | ||
12 | * Portions Copyright (C) 2004, Intel Corporation <jketreno@linux.intel.com> | ||
13 | * | ||
6 | */ | 14 | */ |
7 | 15 | ||
8 | #include <linux/module.h> | 16 | #include <linux/module.h> |
9 | #include <linux/ctype.h> | 17 | #include <linux/ctype.h> |
10 | #include <linux/ieee80211.h> | 18 | #include <linux/ieee80211.h> |
19 | #include <linux/errno.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/string.h> | ||
11 | 23 | ||
12 | #include <net/lib80211.h> | 24 | #include <net/lib80211.h> |
13 | 25 | ||
@@ -19,6 +31,14 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION); | |||
19 | MODULE_AUTHOR("John W. Linville <linville@tuxdriver.com>"); | 31 | MODULE_AUTHOR("John W. Linville <linville@tuxdriver.com>"); |
20 | MODULE_LICENSE("GPL"); | 32 | MODULE_LICENSE("GPL"); |
21 | 33 | ||
34 | struct lib80211_crypto_alg { | ||
35 | struct list_head list; | ||
36 | struct lib80211_crypto_ops *ops; | ||
37 | }; | ||
38 | |||
39 | static LIST_HEAD(lib80211_crypto_algs); | ||
40 | static DEFINE_SPINLOCK(lib80211_crypto_lock); | ||
41 | |||
22 | const char *print_ssid(char *buf, const char *ssid, u8 ssid_len) | 42 | const char *print_ssid(char *buf, const char *ssid, u8 ssid_len) |
23 | { | 43 | { |
24 | const char *s = ssid; | 44 | const char *s = ssid; |
@@ -51,15 +71,176 @@ const char *print_ssid(char *buf, const char *ssid, u8 ssid_len) | |||
51 | } | 71 | } |
52 | EXPORT_SYMBOL(print_ssid); | 72 | EXPORT_SYMBOL(print_ssid); |
53 | 73 | ||
54 | static int __init ieee80211_init(void) | 74 | void lib80211_crypt_deinit_entries(struct lib80211_crypt_info *info, int force) |
55 | { | 75 | { |
56 | printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION "\n"); | 76 | struct lib80211_crypt_data *entry, *next; |
77 | unsigned long flags; | ||
78 | |||
79 | spin_lock_irqsave(info->lock, flags); | ||
80 | list_for_each_entry_safe(entry, next, &info->crypt_deinit_list, list) { | ||
81 | if (atomic_read(&entry->refcnt) != 0 && !force) | ||
82 | continue; | ||
83 | |||
84 | list_del(&entry->list); | ||
85 | |||
86 | if (entry->ops) { | ||
87 | entry->ops->deinit(entry->priv); | ||
88 | module_put(entry->ops->owner); | ||
89 | } | ||
90 | kfree(entry); | ||
91 | } | ||
92 | spin_unlock_irqrestore(info->lock, flags); | ||
93 | } | ||
94 | EXPORT_SYMBOL(lib80211_crypt_deinit_entries); | ||
95 | |||
96 | /* After this, crypt_deinit_list won't accept new members */ | ||
97 | void lib80211_crypt_quiescing(struct lib80211_crypt_info *info) | ||
98 | { | ||
99 | unsigned long flags; | ||
100 | |||
101 | spin_lock_irqsave(info->lock, flags); | ||
102 | info->crypt_quiesced = 1; | ||
103 | spin_unlock_irqrestore(info->lock, flags); | ||
104 | } | ||
105 | EXPORT_SYMBOL(lib80211_crypt_quiescing); | ||
106 | |||
107 | void lib80211_crypt_deinit_handler(unsigned long data) | ||
108 | { | ||
109 | struct lib80211_crypt_info *info = (struct lib80211_crypt_info *)data; | ||
110 | unsigned long flags; | ||
111 | |||
112 | lib80211_crypt_deinit_entries(info, 0); | ||
113 | |||
114 | spin_lock_irqsave(info->lock, flags); | ||
115 | if (!list_empty(&info->crypt_deinit_list) && !info->crypt_quiesced) { | ||
116 | printk(KERN_DEBUG "%s: entries remaining in delayed crypt " | ||
117 | "deletion list\n", info->name); | ||
118 | info->crypt_deinit_timer.expires = jiffies + HZ; | ||
119 | add_timer(&info->crypt_deinit_timer); | ||
120 | } | ||
121 | spin_unlock_irqrestore(info->lock, flags); | ||
122 | } | ||
123 | EXPORT_SYMBOL(lib80211_crypt_deinit_handler); | ||
124 | |||
125 | void lib80211_crypt_delayed_deinit(struct lib80211_crypt_info *info, | ||
126 | struct lib80211_crypt_data **crypt) | ||
127 | { | ||
128 | struct lib80211_crypt_data *tmp; | ||
129 | unsigned long flags; | ||
130 | |||
131 | if (*crypt == NULL) | ||
132 | return; | ||
133 | |||
134 | tmp = *crypt; | ||
135 | *crypt = NULL; | ||
136 | |||
137 | /* must not run ops->deinit() while there may be pending encrypt or | ||
138 | * decrypt operations. Use a list of delayed deinits to avoid needing | ||
139 | * locking. */ | ||
140 | |||
141 | spin_lock_irqsave(info->lock, flags); | ||
142 | if (!info->crypt_quiesced) { | ||
143 | list_add(&tmp->list, &info->crypt_deinit_list); | ||
144 | if (!timer_pending(&info->crypt_deinit_timer)) { | ||
145 | info->crypt_deinit_timer.expires = jiffies + HZ; | ||
146 | add_timer(&info->crypt_deinit_timer); | ||
147 | } | ||
148 | } | ||
149 | spin_unlock_irqrestore(info->lock, flags); | ||
150 | } | ||
151 | EXPORT_SYMBOL(lib80211_crypt_delayed_deinit); | ||
152 | |||
153 | int lib80211_register_crypto_ops(struct lib80211_crypto_ops *ops) | ||
154 | { | ||
155 | unsigned long flags; | ||
156 | struct lib80211_crypto_alg *alg; | ||
157 | |||
158 | alg = kzalloc(sizeof(*alg), GFP_KERNEL); | ||
159 | if (alg == NULL) | ||
160 | return -ENOMEM; | ||
161 | |||
162 | alg->ops = ops; | ||
163 | |||
164 | spin_lock_irqsave(&lib80211_crypto_lock, flags); | ||
165 | list_add(&alg->list, &lib80211_crypto_algs); | ||
166 | spin_unlock_irqrestore(&lib80211_crypto_lock, flags); | ||
167 | |||
168 | printk(KERN_DEBUG "lib80211_crypt: registered algorithm '%s'\n", | ||
169 | ops->name); | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | EXPORT_SYMBOL(lib80211_register_crypto_ops); | ||
174 | |||
175 | int lib80211_unregister_crypto_ops(struct lib80211_crypto_ops *ops) | ||
176 | { | ||
177 | struct lib80211_crypto_alg *alg; | ||
178 | unsigned long flags; | ||
179 | |||
180 | spin_lock_irqsave(&lib80211_crypto_lock, flags); | ||
181 | list_for_each_entry(alg, &lib80211_crypto_algs, list) { | ||
182 | if (alg->ops == ops) | ||
183 | goto found; | ||
184 | } | ||
185 | spin_unlock_irqrestore(&lib80211_crypto_lock, flags); | ||
186 | return -EINVAL; | ||
187 | |||
188 | found: | ||
189 | printk(KERN_DEBUG "lib80211_crypt: unregistered algorithm " | ||
190 | "'%s'\n", ops->name); | ||
191 | list_del(&alg->list); | ||
192 | spin_unlock_irqrestore(&lib80211_crypto_lock, flags); | ||
193 | kfree(alg); | ||
57 | return 0; | 194 | return 0; |
58 | } | 195 | } |
196 | EXPORT_SYMBOL(lib80211_unregister_crypto_ops); | ||
197 | |||
198 | struct lib80211_crypto_ops *lib80211_get_crypto_ops(const char *name) | ||
199 | { | ||
200 | struct lib80211_crypto_alg *alg; | ||
201 | unsigned long flags; | ||
202 | |||
203 | spin_lock_irqsave(&lib80211_crypto_lock, flags); | ||
204 | list_for_each_entry(alg, &lib80211_crypto_algs, list) { | ||
205 | if (strcmp(alg->ops->name, name) == 0) | ||
206 | goto found; | ||
207 | } | ||
208 | spin_unlock_irqrestore(&lib80211_crypto_lock, flags); | ||
209 | return NULL; | ||
210 | |||
211 | found: | ||
212 | spin_unlock_irqrestore(&lib80211_crypto_lock, flags); | ||
213 | return alg->ops; | ||
214 | } | ||
215 | EXPORT_SYMBOL(lib80211_get_crypto_ops); | ||
216 | |||
217 | static void *lib80211_crypt_null_init(int keyidx) | ||
218 | { | ||
219 | return (void *)1; | ||
220 | } | ||
221 | |||
222 | static void lib80211_crypt_null_deinit(void *priv) | ||
223 | { | ||
224 | } | ||
225 | |||
226 | static struct lib80211_crypto_ops lib80211_crypt_null = { | ||
227 | .name = "NULL", | ||
228 | .init = lib80211_crypt_null_init, | ||
229 | .deinit = lib80211_crypt_null_deinit, | ||
230 | .owner = THIS_MODULE, | ||
231 | }; | ||
232 | |||
233 | static int __init lib80211_init(void) | ||
234 | { | ||
235 | printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION "\n"); | ||
236 | return lib80211_register_crypto_ops(&lib80211_crypt_null); | ||
237 | } | ||
59 | 238 | ||
60 | static void __exit ieee80211_exit(void) | 239 | static void __exit lib80211_exit(void) |
61 | { | 240 | { |
241 | lib80211_unregister_crypto_ops(&lib80211_crypt_null); | ||
242 | BUG_ON(!list_empty(&lib80211_crypto_algs)); | ||
62 | } | 243 | } |
63 | 244 | ||
64 | module_init(ieee80211_init); | 245 | module_init(lib80211_init); |
65 | module_exit(ieee80211_exit); | 246 | module_exit(lib80211_exit); |
diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/wireless/lib80211_crypt_ccmp.c index bea04af0b482..db428194c16a 100644 --- a/net/ieee80211/ieee80211_crypt_ccmp.c +++ b/net/wireless/lib80211_crypt_ccmp.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Host AP crypt: host-based CCMP encryption implementation for Host AP driver | 2 | * lib80211 crypt: host-based CCMP encryption implementation for lib80211 |
3 | * | 3 | * |
4 | * Copyright (c) 2003-2004, Jouni Malinen <j@w1.fi> | 4 | * Copyright (c) 2003-2004, Jouni Malinen <j@w1.fi> |
5 | * Copyright (c) 2008, John W. Linville <linville@tuxdriver.com> | ||
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify | 7 | * 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 | * it under the terms of the GNU General Public License version 2 as |
@@ -22,10 +23,12 @@ | |||
22 | #include <asm/string.h> | 23 | #include <asm/string.h> |
23 | #include <linux/wireless.h> | 24 | #include <linux/wireless.h> |
24 | 25 | ||
25 | #include <net/ieee80211.h> | 26 | #include <linux/ieee80211.h> |
26 | 27 | ||
27 | #include <linux/crypto.h> | 28 | #include <linux/crypto.h> |
28 | 29 | ||
30 | #include <net/lib80211.h> | ||
31 | |||
29 | MODULE_AUTHOR("Jouni Malinen"); | 32 | MODULE_AUTHOR("Jouni Malinen"); |
30 | MODULE_DESCRIPTION("Host AP crypt: CCMP"); | 33 | MODULE_DESCRIPTION("Host AP crypt: CCMP"); |
31 | MODULE_LICENSE("GPL"); | 34 | MODULE_LICENSE("GPL"); |
@@ -36,7 +39,7 @@ MODULE_LICENSE("GPL"); | |||
36 | #define CCMP_TK_LEN 16 | 39 | #define CCMP_TK_LEN 16 |
37 | #define CCMP_PN_LEN 6 | 40 | #define CCMP_PN_LEN 6 |
38 | 41 | ||
39 | struct ieee80211_ccmp_data { | 42 | struct lib80211_ccmp_data { |
40 | u8 key[CCMP_TK_LEN]; | 43 | u8 key[CCMP_TK_LEN]; |
41 | int key_set; | 44 | int key_set; |
42 | 45 | ||
@@ -57,15 +60,15 @@ struct ieee80211_ccmp_data { | |||
57 | u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN]; | 60 | u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN]; |
58 | }; | 61 | }; |
59 | 62 | ||
60 | static inline void ieee80211_ccmp_aes_encrypt(struct crypto_cipher *tfm, | 63 | static inline void lib80211_ccmp_aes_encrypt(struct crypto_cipher *tfm, |
61 | const u8 pt[16], u8 ct[16]) | 64 | const u8 pt[16], u8 ct[16]) |
62 | { | 65 | { |
63 | crypto_cipher_encrypt_one(tfm, ct, pt); | 66 | crypto_cipher_encrypt_one(tfm, ct, pt); |
64 | } | 67 | } |
65 | 68 | ||
66 | static void *ieee80211_ccmp_init(int key_idx) | 69 | static void *lib80211_ccmp_init(int key_idx) |
67 | { | 70 | { |
68 | struct ieee80211_ccmp_data *priv; | 71 | struct lib80211_ccmp_data *priv; |
69 | 72 | ||
70 | priv = kzalloc(sizeof(*priv), GFP_ATOMIC); | 73 | priv = kzalloc(sizeof(*priv), GFP_ATOMIC); |
71 | if (priv == NULL) | 74 | if (priv == NULL) |
@@ -74,7 +77,7 @@ static void *ieee80211_ccmp_init(int key_idx) | |||
74 | 77 | ||
75 | priv->tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); | 78 | priv->tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); |
76 | if (IS_ERR(priv->tfm)) { | 79 | if (IS_ERR(priv->tfm)) { |
77 | printk(KERN_DEBUG "ieee80211_crypt_ccmp: could not allocate " | 80 | printk(KERN_DEBUG "lib80211_crypt_ccmp: could not allocate " |
78 | "crypto API aes\n"); | 81 | "crypto API aes\n"); |
79 | priv->tfm = NULL; | 82 | priv->tfm = NULL; |
80 | goto fail; | 83 | goto fail; |
@@ -92,9 +95,9 @@ static void *ieee80211_ccmp_init(int key_idx) | |||
92 | return NULL; | 95 | return NULL; |
93 | } | 96 | } |
94 | 97 | ||
95 | static void ieee80211_ccmp_deinit(void *priv) | 98 | static void lib80211_ccmp_deinit(void *priv) |
96 | { | 99 | { |
97 | struct ieee80211_ccmp_data *_priv = priv; | 100 | struct lib80211_ccmp_data *_priv = priv; |
98 | if (_priv && _priv->tfm) | 101 | if (_priv && _priv->tfm) |
99 | crypto_free_cipher(_priv->tfm); | 102 | crypto_free_cipher(_priv->tfm); |
100 | kfree(priv); | 103 | kfree(priv); |
@@ -108,20 +111,17 @@ static inline void xor_block(u8 * b, u8 * a, size_t len) | |||
108 | } | 111 | } |
109 | 112 | ||
110 | static void ccmp_init_blocks(struct crypto_cipher *tfm, | 113 | static void ccmp_init_blocks(struct crypto_cipher *tfm, |
111 | struct ieee80211_hdr_4addr *hdr, | 114 | struct ieee80211_hdr *hdr, |
112 | u8 * pn, size_t dlen, u8 * b0, u8 * auth, u8 * s0) | 115 | u8 * pn, size_t dlen, u8 * b0, u8 * auth, u8 * s0) |
113 | { | 116 | { |
114 | u8 *pos, qc = 0; | 117 | u8 *pos, qc = 0; |
115 | size_t aad_len; | 118 | size_t aad_len; |
116 | u16 fc; | ||
117 | int a4_included, qc_included; | 119 | int a4_included, qc_included; |
118 | u8 aad[2 * AES_BLOCK_LEN]; | 120 | u8 aad[2 * AES_BLOCK_LEN]; |
119 | 121 | ||
120 | fc = le16_to_cpu(hdr->frame_ctl); | 122 | a4_included = ieee80211_has_a4(hdr->frame_control); |
121 | a4_included = ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == | 123 | qc_included = ieee80211_is_data_qos(hdr->frame_control); |
122 | (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)); | 124 | |
123 | qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) && | ||
124 | (WLAN_FC_GET_STYPE(fc) & IEEE80211_STYPE_QOS_DATA)); | ||
125 | aad_len = 22; | 125 | aad_len = 22; |
126 | if (a4_included) | 126 | if (a4_included) |
127 | aad_len += 6; | 127 | aad_len += 6; |
@@ -158,7 +158,7 @@ static void ccmp_init_blocks(struct crypto_cipher *tfm, | |||
158 | aad[2] = pos[0] & 0x8f; | 158 | aad[2] = pos[0] & 0x8f; |
159 | aad[3] = pos[1] & 0xc7; | 159 | aad[3] = pos[1] & 0xc7; |
160 | memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN); | 160 | memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN); |
161 | pos = (u8 *) & hdr->seq_ctl; | 161 | pos = (u8 *) & hdr->seq_ctrl; |
162 | aad[22] = pos[0] & 0x0f; | 162 | aad[22] = pos[0] & 0x0f; |
163 | aad[23] = 0; /* all bits masked */ | 163 | aad[23] = 0; /* all bits masked */ |
164 | memset(aad + 24, 0, 8); | 164 | memset(aad + 24, 0, 8); |
@@ -170,20 +170,20 @@ static void ccmp_init_blocks(struct crypto_cipher *tfm, | |||
170 | } | 170 | } |
171 | 171 | ||
172 | /* Start with the first block and AAD */ | 172 | /* Start with the first block and AAD */ |
173 | ieee80211_ccmp_aes_encrypt(tfm, b0, auth); | 173 | lib80211_ccmp_aes_encrypt(tfm, b0, auth); |
174 | xor_block(auth, aad, AES_BLOCK_LEN); | 174 | xor_block(auth, aad, AES_BLOCK_LEN); |
175 | ieee80211_ccmp_aes_encrypt(tfm, auth, auth); | 175 | lib80211_ccmp_aes_encrypt(tfm, auth, auth); |
176 | xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN); | 176 | xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN); |
177 | ieee80211_ccmp_aes_encrypt(tfm, auth, auth); | 177 | lib80211_ccmp_aes_encrypt(tfm, auth, auth); |
178 | b0[0] &= 0x07; | 178 | b0[0] &= 0x07; |
179 | b0[14] = b0[15] = 0; | 179 | b0[14] = b0[15] = 0; |
180 | ieee80211_ccmp_aes_encrypt(tfm, b0, s0); | 180 | lib80211_ccmp_aes_encrypt(tfm, b0, s0); |
181 | } | 181 | } |
182 | 182 | ||
183 | static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len, | 183 | static int lib80211_ccmp_hdr(struct sk_buff *skb, int hdr_len, |
184 | u8 *aeskey, int keylen, void *priv) | 184 | u8 *aeskey, int keylen, void *priv) |
185 | { | 185 | { |
186 | struct ieee80211_ccmp_data *key = priv; | 186 | struct lib80211_ccmp_data *key = priv; |
187 | int i; | 187 | int i; |
188 | u8 *pos; | 188 | u8 *pos; |
189 | 189 | ||
@@ -217,12 +217,12 @@ static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len, | |||
217 | return CCMP_HDR_LEN; | 217 | return CCMP_HDR_LEN; |
218 | } | 218 | } |
219 | 219 | ||
220 | static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) | 220 | static int lib80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) |
221 | { | 221 | { |
222 | struct ieee80211_ccmp_data *key = priv; | 222 | struct lib80211_ccmp_data *key = priv; |
223 | int data_len, i, blocks, last, len; | 223 | int data_len, i, blocks, last, len; |
224 | u8 *pos, *mic; | 224 | u8 *pos, *mic; |
225 | struct ieee80211_hdr_4addr *hdr; | 225 | struct ieee80211_hdr *hdr; |
226 | u8 *b0 = key->tx_b0; | 226 | u8 *b0 = key->tx_b0; |
227 | u8 *b = key->tx_b; | 227 | u8 *b = key->tx_b; |
228 | u8 *e = key->tx_e; | 228 | u8 *e = key->tx_e; |
@@ -232,13 +232,13 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
232 | return -1; | 232 | return -1; |
233 | 233 | ||
234 | data_len = skb->len - hdr_len; | 234 | data_len = skb->len - hdr_len; |
235 | len = ieee80211_ccmp_hdr(skb, hdr_len, NULL, 0, priv); | 235 | len = lib80211_ccmp_hdr(skb, hdr_len, NULL, 0, priv); |
236 | if (len < 0) | 236 | if (len < 0) |
237 | return -1; | 237 | return -1; |
238 | 238 | ||
239 | pos = skb->data + hdr_len + CCMP_HDR_LEN; | 239 | pos = skb->data + hdr_len + CCMP_HDR_LEN; |
240 | mic = skb_put(skb, CCMP_MIC_LEN); | 240 | mic = skb_put(skb, CCMP_MIC_LEN); |
241 | hdr = (struct ieee80211_hdr_4addr *)skb->data; | 241 | hdr = (struct ieee80211_hdr *)skb->data; |
242 | ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0); | 242 | ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0); |
243 | 243 | ||
244 | blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); | 244 | blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); |
@@ -248,11 +248,11 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
248 | len = (i == blocks && last) ? last : AES_BLOCK_LEN; | 248 | len = (i == blocks && last) ? last : AES_BLOCK_LEN; |
249 | /* Authentication */ | 249 | /* Authentication */ |
250 | xor_block(b, pos, len); | 250 | xor_block(b, pos, len); |
251 | ieee80211_ccmp_aes_encrypt(key->tfm, b, b); | 251 | lib80211_ccmp_aes_encrypt(key->tfm, b, b); |
252 | /* Encryption, with counter */ | 252 | /* Encryption, with counter */ |
253 | b0[14] = (i >> 8) & 0xff; | 253 | b0[14] = (i >> 8) & 0xff; |
254 | b0[15] = i & 0xff; | 254 | b0[15] = i & 0xff; |
255 | ieee80211_ccmp_aes_encrypt(key->tfm, b0, e); | 255 | lib80211_ccmp_aes_encrypt(key->tfm, b0, e); |
256 | xor_block(pos, e, len); | 256 | xor_block(pos, e, len); |
257 | pos += len; | 257 | pos += len; |
258 | } | 258 | } |
@@ -284,11 +284,11 @@ static inline int ccmp_replay_check(u8 *pn_n, u8 *pn_o) | |||
284 | return 0; | 284 | return 0; |
285 | } | 285 | } |
286 | 286 | ||
287 | static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | 287 | static int lib80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) |
288 | { | 288 | { |
289 | struct ieee80211_ccmp_data *key = priv; | 289 | struct lib80211_ccmp_data *key = priv; |
290 | u8 keyidx, *pos; | 290 | u8 keyidx, *pos; |
291 | struct ieee80211_hdr_4addr *hdr; | 291 | struct ieee80211_hdr *hdr; |
292 | u8 *b0 = key->rx_b0; | 292 | u8 *b0 = key->rx_b0; |
293 | u8 *b = key->rx_b; | 293 | u8 *b = key->rx_b; |
294 | u8 *a = key->rx_a; | 294 | u8 *a = key->rx_a; |
@@ -302,7 +302,7 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
302 | return -1; | 302 | return -1; |
303 | } | 303 | } |
304 | 304 | ||
305 | hdr = (struct ieee80211_hdr_4addr *)skb->data; | 305 | hdr = (struct ieee80211_hdr *)skb->data; |
306 | pos = skb->data + hdr_len; | 306 | pos = skb->data + hdr_len; |
307 | keyidx = pos[3]; | 307 | keyidx = pos[3]; |
308 | if (!(keyidx & (1 << 5))) { | 308 | if (!(keyidx & (1 << 5))) { |
@@ -337,8 +337,8 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
337 | pos += 8; | 337 | pos += 8; |
338 | 338 | ||
339 | if (ccmp_replay_check(pn, key->rx_pn)) { | 339 | if (ccmp_replay_check(pn, key->rx_pn)) { |
340 | if (ieee80211_ratelimit_debug(IEEE80211_DL_DROP)) { | 340 | if (net_ratelimit()) { |
341 | IEEE80211_DEBUG_DROP("CCMP: replay detected: STA=%pM " | 341 | printk(KERN_DEBUG "CCMP: replay detected: STA=%pM " |
342 | "previous PN %02x%02x%02x%02x%02x%02x " | 342 | "previous PN %02x%02x%02x%02x%02x%02x " |
343 | "received PN %02x%02x%02x%02x%02x%02x\n", | 343 | "received PN %02x%02x%02x%02x%02x%02x\n", |
344 | hdr->addr2, | 344 | hdr->addr2, |
@@ -361,11 +361,11 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
361 | /* Decrypt, with counter */ | 361 | /* Decrypt, with counter */ |
362 | b0[14] = (i >> 8) & 0xff; | 362 | b0[14] = (i >> 8) & 0xff; |
363 | b0[15] = i & 0xff; | 363 | b0[15] = i & 0xff; |
364 | ieee80211_ccmp_aes_encrypt(key->tfm, b0, b); | 364 | lib80211_ccmp_aes_encrypt(key->tfm, b0, b); |
365 | xor_block(pos, b, len); | 365 | xor_block(pos, b, len); |
366 | /* Authentication */ | 366 | /* Authentication */ |
367 | xor_block(a, pos, len); | 367 | xor_block(a, pos, len); |
368 | ieee80211_ccmp_aes_encrypt(key->tfm, a, a); | 368 | lib80211_ccmp_aes_encrypt(key->tfm, a, a); |
369 | pos += len; | 369 | pos += len; |
370 | } | 370 | } |
371 | 371 | ||
@@ -388,9 +388,9 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
388 | return keyidx; | 388 | return keyidx; |
389 | } | 389 | } |
390 | 390 | ||
391 | static int ieee80211_ccmp_set_key(void *key, int len, u8 * seq, void *priv) | 391 | static int lib80211_ccmp_set_key(void *key, int len, u8 * seq, void *priv) |
392 | { | 392 | { |
393 | struct ieee80211_ccmp_data *data = priv; | 393 | struct lib80211_ccmp_data *data = priv; |
394 | int keyidx; | 394 | int keyidx; |
395 | struct crypto_cipher *tfm = data->tfm; | 395 | struct crypto_cipher *tfm = data->tfm; |
396 | 396 | ||
@@ -418,9 +418,9 @@ static int ieee80211_ccmp_set_key(void *key, int len, u8 * seq, void *priv) | |||
418 | return 0; | 418 | return 0; |
419 | } | 419 | } |
420 | 420 | ||
421 | static int ieee80211_ccmp_get_key(void *key, int len, u8 * seq, void *priv) | 421 | static int lib80211_ccmp_get_key(void *key, int len, u8 * seq, void *priv) |
422 | { | 422 | { |
423 | struct ieee80211_ccmp_data *data = priv; | 423 | struct lib80211_ccmp_data *data = priv; |
424 | 424 | ||
425 | if (len < CCMP_TK_LEN) | 425 | if (len < CCMP_TK_LEN) |
426 | return -1; | 426 | return -1; |
@@ -441,9 +441,9 @@ static int ieee80211_ccmp_get_key(void *key, int len, u8 * seq, void *priv) | |||
441 | return CCMP_TK_LEN; | 441 | return CCMP_TK_LEN; |
442 | } | 442 | } |
443 | 443 | ||
444 | static char *ieee80211_ccmp_print_stats(char *p, void *priv) | 444 | static char *lib80211_ccmp_print_stats(char *p, void *priv) |
445 | { | 445 | { |
446 | struct ieee80211_ccmp_data *ccmp = priv; | 446 | struct lib80211_ccmp_data *ccmp = priv; |
447 | 447 | ||
448 | p += sprintf(p, "key[%d] alg=CCMP key_set=%d " | 448 | p += sprintf(p, "key[%d] alg=CCMP key_set=%d " |
449 | "tx_pn=%02x%02x%02x%02x%02x%02x " | 449 | "tx_pn=%02x%02x%02x%02x%02x%02x " |
@@ -461,32 +461,32 @@ static char *ieee80211_ccmp_print_stats(char *p, void *priv) | |||
461 | return p; | 461 | return p; |
462 | } | 462 | } |
463 | 463 | ||
464 | static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = { | 464 | static struct lib80211_crypto_ops lib80211_crypt_ccmp = { |
465 | .name = "CCMP", | 465 | .name = "CCMP", |
466 | .init = ieee80211_ccmp_init, | 466 | .init = lib80211_ccmp_init, |
467 | .deinit = ieee80211_ccmp_deinit, | 467 | .deinit = lib80211_ccmp_deinit, |
468 | .build_iv = ieee80211_ccmp_hdr, | 468 | .build_iv = lib80211_ccmp_hdr, |
469 | .encrypt_mpdu = ieee80211_ccmp_encrypt, | 469 | .encrypt_mpdu = lib80211_ccmp_encrypt, |
470 | .decrypt_mpdu = ieee80211_ccmp_decrypt, | 470 | .decrypt_mpdu = lib80211_ccmp_decrypt, |
471 | .encrypt_msdu = NULL, | 471 | .encrypt_msdu = NULL, |
472 | .decrypt_msdu = NULL, | 472 | .decrypt_msdu = NULL, |
473 | .set_key = ieee80211_ccmp_set_key, | 473 | .set_key = lib80211_ccmp_set_key, |
474 | .get_key = ieee80211_ccmp_get_key, | 474 | .get_key = lib80211_ccmp_get_key, |
475 | .print_stats = ieee80211_ccmp_print_stats, | 475 | .print_stats = lib80211_ccmp_print_stats, |
476 | .extra_mpdu_prefix_len = CCMP_HDR_LEN, | 476 | .extra_mpdu_prefix_len = CCMP_HDR_LEN, |
477 | .extra_mpdu_postfix_len = CCMP_MIC_LEN, | 477 | .extra_mpdu_postfix_len = CCMP_MIC_LEN, |
478 | .owner = THIS_MODULE, | 478 | .owner = THIS_MODULE, |
479 | }; | 479 | }; |
480 | 480 | ||
481 | static int __init ieee80211_crypto_ccmp_init(void) | 481 | static int __init lib80211_crypto_ccmp_init(void) |
482 | { | 482 | { |
483 | return ieee80211_register_crypto_ops(&ieee80211_crypt_ccmp); | 483 | return lib80211_register_crypto_ops(&lib80211_crypt_ccmp); |
484 | } | 484 | } |
485 | 485 | ||
486 | static void __exit ieee80211_crypto_ccmp_exit(void) | 486 | static void __exit lib80211_crypto_ccmp_exit(void) |
487 | { | 487 | { |
488 | ieee80211_unregister_crypto_ops(&ieee80211_crypt_ccmp); | 488 | lib80211_unregister_crypto_ops(&lib80211_crypt_ccmp); |
489 | } | 489 | } |
490 | 490 | ||
491 | module_init(ieee80211_crypto_ccmp_init); | 491 | module_init(lib80211_crypto_ccmp_init); |
492 | module_exit(ieee80211_crypto_ccmp_exit); | 492 | module_exit(lib80211_crypto_ccmp_exit); |
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/wireless/lib80211_crypt_tkip.c index d12da1da6328..7e8e22bfed90 100644 --- a/net/ieee80211/ieee80211_crypt_tkip.c +++ b/net/wireless/lib80211_crypt_tkip.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Host AP crypt: host-based TKIP encryption implementation for Host AP driver | 2 | * lib80211 crypt: host-based TKIP encryption implementation for lib80211 |
3 | * | 3 | * |
4 | * Copyright (c) 2003-2004, Jouni Malinen <j@w1.fi> | 4 | * Copyright (c) 2003-2004, Jouni Malinen <j@w1.fi> |
5 | * Copyright (c) 2008, John W. Linville <linville@tuxdriver.com> | ||
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify | 7 | * 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 | * it under the terms of the GNU General Public License version 2 as |
@@ -22,16 +23,20 @@ | |||
22 | #include <linux/if_arp.h> | 23 | #include <linux/if_arp.h> |
23 | #include <asm/string.h> | 24 | #include <asm/string.h> |
24 | 25 | ||
25 | #include <net/ieee80211.h> | 26 | #include <linux/wireless.h> |
27 | #include <linux/ieee80211.h> | ||
28 | #include <net/iw_handler.h> | ||
26 | 29 | ||
27 | #include <linux/crypto.h> | 30 | #include <linux/crypto.h> |
28 | #include <linux/crc32.h> | 31 | #include <linux/crc32.h> |
29 | 32 | ||
33 | #include <net/lib80211.h> | ||
34 | |||
30 | MODULE_AUTHOR("Jouni Malinen"); | 35 | MODULE_AUTHOR("Jouni Malinen"); |
31 | MODULE_DESCRIPTION("Host AP crypt: TKIP"); | 36 | MODULE_DESCRIPTION("lib80211 crypt: TKIP"); |
32 | MODULE_LICENSE("GPL"); | 37 | MODULE_LICENSE("GPL"); |
33 | 38 | ||
34 | struct ieee80211_tkip_data { | 39 | struct lib80211_tkip_data { |
35 | #define TKIP_KEY_LEN 32 | 40 | #define TKIP_KEY_LEN 32 |
36 | u8 key[TKIP_KEY_LEN]; | 41 | u8 key[TKIP_KEY_LEN]; |
37 | int key_set; | 42 | int key_set; |
@@ -65,23 +70,23 @@ struct ieee80211_tkip_data { | |||
65 | unsigned long flags; | 70 | unsigned long flags; |
66 | }; | 71 | }; |
67 | 72 | ||
68 | static unsigned long ieee80211_tkip_set_flags(unsigned long flags, void *priv) | 73 | static unsigned long lib80211_tkip_set_flags(unsigned long flags, void *priv) |
69 | { | 74 | { |
70 | struct ieee80211_tkip_data *_priv = priv; | 75 | struct lib80211_tkip_data *_priv = priv; |
71 | unsigned long old_flags = _priv->flags; | 76 | unsigned long old_flags = _priv->flags; |
72 | _priv->flags = flags; | 77 | _priv->flags = flags; |
73 | return old_flags; | 78 | return old_flags; |
74 | } | 79 | } |
75 | 80 | ||
76 | static unsigned long ieee80211_tkip_get_flags(void *priv) | 81 | static unsigned long lib80211_tkip_get_flags(void *priv) |
77 | { | 82 | { |
78 | struct ieee80211_tkip_data *_priv = priv; | 83 | struct lib80211_tkip_data *_priv = priv; |
79 | return _priv->flags; | 84 | return _priv->flags; |
80 | } | 85 | } |
81 | 86 | ||
82 | static void *ieee80211_tkip_init(int key_idx) | 87 | static void *lib80211_tkip_init(int key_idx) |
83 | { | 88 | { |
84 | struct ieee80211_tkip_data *priv; | 89 | struct lib80211_tkip_data *priv; |
85 | 90 | ||
86 | priv = kzalloc(sizeof(*priv), GFP_ATOMIC); | 91 | priv = kzalloc(sizeof(*priv), GFP_ATOMIC); |
87 | if (priv == NULL) | 92 | if (priv == NULL) |
@@ -92,7 +97,7 @@ static void *ieee80211_tkip_init(int key_idx) | |||
92 | priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, | 97 | priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, |
93 | CRYPTO_ALG_ASYNC); | 98 | CRYPTO_ALG_ASYNC); |
94 | if (IS_ERR(priv->tx_tfm_arc4)) { | 99 | if (IS_ERR(priv->tx_tfm_arc4)) { |
95 | printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " | 100 | printk(KERN_DEBUG "lib80211_crypt_tkip: could not allocate " |
96 | "crypto API arc4\n"); | 101 | "crypto API arc4\n"); |
97 | priv->tx_tfm_arc4 = NULL; | 102 | priv->tx_tfm_arc4 = NULL; |
98 | goto fail; | 103 | goto fail; |
@@ -101,7 +106,7 @@ static void *ieee80211_tkip_init(int key_idx) | |||
101 | priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0, | 106 | priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0, |
102 | CRYPTO_ALG_ASYNC); | 107 | CRYPTO_ALG_ASYNC); |
103 | if (IS_ERR(priv->tx_tfm_michael)) { | 108 | if (IS_ERR(priv->tx_tfm_michael)) { |
104 | printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " | 109 | printk(KERN_DEBUG "lib80211_crypt_tkip: could not allocate " |
105 | "crypto API michael_mic\n"); | 110 | "crypto API michael_mic\n"); |
106 | priv->tx_tfm_michael = NULL; | 111 | priv->tx_tfm_michael = NULL; |
107 | goto fail; | 112 | goto fail; |
@@ -110,7 +115,7 @@ static void *ieee80211_tkip_init(int key_idx) | |||
110 | priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, | 115 | priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, |
111 | CRYPTO_ALG_ASYNC); | 116 | CRYPTO_ALG_ASYNC); |
112 | if (IS_ERR(priv->rx_tfm_arc4)) { | 117 | if (IS_ERR(priv->rx_tfm_arc4)) { |
113 | printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " | 118 | printk(KERN_DEBUG "lib80211_crypt_tkip: could not allocate " |
114 | "crypto API arc4\n"); | 119 | "crypto API arc4\n"); |
115 | priv->rx_tfm_arc4 = NULL; | 120 | priv->rx_tfm_arc4 = NULL; |
116 | goto fail; | 121 | goto fail; |
@@ -119,7 +124,7 @@ static void *ieee80211_tkip_init(int key_idx) | |||
119 | priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0, | 124 | priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0, |
120 | CRYPTO_ALG_ASYNC); | 125 | CRYPTO_ALG_ASYNC); |
121 | if (IS_ERR(priv->rx_tfm_michael)) { | 126 | if (IS_ERR(priv->rx_tfm_michael)) { |
122 | printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " | 127 | printk(KERN_DEBUG "lib80211_crypt_tkip: could not allocate " |
123 | "crypto API michael_mic\n"); | 128 | "crypto API michael_mic\n"); |
124 | priv->rx_tfm_michael = NULL; | 129 | priv->rx_tfm_michael = NULL; |
125 | goto fail; | 130 | goto fail; |
@@ -143,9 +148,9 @@ static void *ieee80211_tkip_init(int key_idx) | |||
143 | return NULL; | 148 | return NULL; |
144 | } | 149 | } |
145 | 150 | ||
146 | static void ieee80211_tkip_deinit(void *priv) | 151 | static void lib80211_tkip_deinit(void *priv) |
147 | { | 152 | { |
148 | struct ieee80211_tkip_data *_priv = priv; | 153 | struct lib80211_tkip_data *_priv = priv; |
149 | if (_priv) { | 154 | if (_priv) { |
150 | if (_priv->tx_tfm_michael) | 155 | if (_priv->tx_tfm_michael) |
151 | crypto_free_hash(_priv->tx_tfm_michael); | 156 | crypto_free_hash(_priv->tx_tfm_michael); |
@@ -305,15 +310,15 @@ static void tkip_mixing_phase2(u8 * WEPSeed, const u8 * TK, const u16 * TTAK, | |||
305 | #endif | 310 | #endif |
306 | } | 311 | } |
307 | 312 | ||
308 | static int ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len, | 313 | static int lib80211_tkip_hdr(struct sk_buff *skb, int hdr_len, |
309 | u8 * rc4key, int keylen, void *priv) | 314 | u8 * rc4key, int keylen, void *priv) |
310 | { | 315 | { |
311 | struct ieee80211_tkip_data *tkey = priv; | 316 | struct lib80211_tkip_data *tkey = priv; |
312 | int len; | 317 | int len; |
313 | u8 *pos; | 318 | u8 *pos; |
314 | struct ieee80211_hdr_4addr *hdr; | 319 | struct ieee80211_hdr *hdr; |
315 | 320 | ||
316 | hdr = (struct ieee80211_hdr_4addr *)skb->data; | 321 | hdr = (struct ieee80211_hdr *)skb->data; |
317 | 322 | ||
318 | if (skb_headroom(skb) < 8 || skb->len < hdr_len) | 323 | if (skb_headroom(skb) < 8 || skb->len < hdr_len) |
319 | return -1; | 324 | return -1; |
@@ -351,9 +356,9 @@ static int ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len, | |||
351 | return 8; | 356 | return 8; |
352 | } | 357 | } |
353 | 358 | ||
354 | static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) | 359 | static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) |
355 | { | 360 | { |
356 | struct ieee80211_tkip_data *tkey = priv; | 361 | struct lib80211_tkip_data *tkey = priv; |
357 | struct blkcipher_desc desc = { .tfm = tkey->tx_tfm_arc4 }; | 362 | struct blkcipher_desc desc = { .tfm = tkey->tx_tfm_arc4 }; |
358 | int len; | 363 | int len; |
359 | u8 rc4key[16], *pos, *icv; | 364 | u8 rc4key[16], *pos, *icv; |
@@ -362,8 +367,8 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
362 | 367 | ||
363 | if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) { | 368 | if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) { |
364 | if (net_ratelimit()) { | 369 | if (net_ratelimit()) { |
365 | struct ieee80211_hdr_4addr *hdr = | 370 | struct ieee80211_hdr *hdr = |
366 | (struct ieee80211_hdr_4addr *)skb->data; | 371 | (struct ieee80211_hdr *)skb->data; |
367 | printk(KERN_DEBUG ": TKIP countermeasures: dropped " | 372 | printk(KERN_DEBUG ": TKIP countermeasures: dropped " |
368 | "TX packet to %pM\n", hdr->addr1); | 373 | "TX packet to %pM\n", hdr->addr1); |
369 | } | 374 | } |
@@ -376,7 +381,7 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
376 | len = skb->len - hdr_len; | 381 | len = skb->len - hdr_len; |
377 | pos = skb->data + hdr_len; | 382 | pos = skb->data + hdr_len; |
378 | 383 | ||
379 | if ((ieee80211_tkip_hdr(skb, hdr_len, rc4key, 16, priv)) < 0) | 384 | if ((lib80211_tkip_hdr(skb, hdr_len, rc4key, 16, priv)) < 0) |
380 | return -1; | 385 | return -1; |
381 | 386 | ||
382 | icv = skb_put(skb, 4); | 387 | icv = skb_put(skb, 4); |
@@ -405,21 +410,21 @@ static inline int tkip_replay_check(u32 iv32_n, u16 iv16_n, | |||
405 | return 0; | 410 | return 0; |
406 | } | 411 | } |
407 | 412 | ||
408 | static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | 413 | static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) |
409 | { | 414 | { |
410 | struct ieee80211_tkip_data *tkey = priv; | 415 | struct lib80211_tkip_data *tkey = priv; |
411 | struct blkcipher_desc desc = { .tfm = tkey->rx_tfm_arc4 }; | 416 | struct blkcipher_desc desc = { .tfm = tkey->rx_tfm_arc4 }; |
412 | u8 rc4key[16]; | 417 | u8 rc4key[16]; |
413 | u8 keyidx, *pos; | 418 | u8 keyidx, *pos; |
414 | u32 iv32; | 419 | u32 iv32; |
415 | u16 iv16; | 420 | u16 iv16; |
416 | struct ieee80211_hdr_4addr *hdr; | 421 | struct ieee80211_hdr *hdr; |
417 | u8 icv[4]; | 422 | u8 icv[4]; |
418 | u32 crc; | 423 | u32 crc; |
419 | struct scatterlist sg; | 424 | struct scatterlist sg; |
420 | int plen; | 425 | int plen; |
421 | 426 | ||
422 | hdr = (struct ieee80211_hdr_4addr *)skb->data; | 427 | hdr = (struct ieee80211_hdr *)skb->data; |
423 | 428 | ||
424 | if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) { | 429 | if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) { |
425 | if (net_ratelimit()) { | 430 | if (net_ratelimit()) { |
@@ -460,8 +465,8 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
460 | pos += 8; | 465 | pos += 8; |
461 | 466 | ||
462 | if (tkip_replay_check(iv32, iv16, tkey->rx_iv32, tkey->rx_iv16)) { | 467 | if (tkip_replay_check(iv32, iv16, tkey->rx_iv32, tkey->rx_iv16)) { |
463 | if (ieee80211_ratelimit_debug(IEEE80211_DL_DROP)) { | 468 | if (net_ratelimit()) { |
464 | IEEE80211_DEBUG_DROP("TKIP: replay detected: STA=%pM" | 469 | printk(KERN_DEBUG "TKIP: replay detected: STA=%pM" |
465 | " previous TSC %08x%04x received TSC " | 470 | " previous TSC %08x%04x received TSC " |
466 | "%08x%04x\n", hdr->addr2, | 471 | "%08x%04x\n", hdr->addr2, |
467 | tkey->rx_iv32, tkey->rx_iv16, iv32, iv16); | 472 | tkey->rx_iv32, tkey->rx_iv16, iv32, iv16); |
@@ -500,8 +505,8 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
500 | * it needs to be recalculated for the next packet. */ | 505 | * it needs to be recalculated for the next packet. */ |
501 | tkey->rx_phase1_done = 0; | 506 | tkey->rx_phase1_done = 0; |
502 | } | 507 | } |
503 | if (ieee80211_ratelimit_debug(IEEE80211_DL_DROP)) { | 508 | if (net_ratelimit()) { |
504 | IEEE80211_DEBUG_DROP("TKIP: ICV error detected: STA=" | 509 | printk(KERN_DEBUG "TKIP: ICV error detected: STA=" |
505 | "%pM\n", hdr->addr2); | 510 | "%pM\n", hdr->addr2); |
506 | } | 511 | } |
507 | tkey->dot11RSNAStatsTKIPICVErrors++; | 512 | tkey->dot11RSNAStatsTKIPICVErrors++; |
@@ -545,13 +550,11 @@ static int michael_mic(struct crypto_hash *tfm_michael, u8 * key, u8 * hdr, | |||
545 | 550 | ||
546 | static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr) | 551 | static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr) |
547 | { | 552 | { |
548 | struct ieee80211_hdr_4addr *hdr11; | 553 | struct ieee80211_hdr *hdr11; |
549 | u16 stype; | ||
550 | 554 | ||
551 | hdr11 = (struct ieee80211_hdr_4addr *)skb->data; | 555 | hdr11 = (struct ieee80211_hdr *)skb->data; |
552 | stype = WLAN_FC_GET_STYPE(le16_to_cpu(hdr11->frame_ctl)); | ||
553 | 556 | ||
554 | switch (le16_to_cpu(hdr11->frame_ctl) & | 557 | switch (le16_to_cpu(hdr11->frame_control) & |
555 | (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { | 558 | (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { |
556 | case IEEE80211_FCTL_TODS: | 559 | case IEEE80211_FCTL_TODS: |
557 | memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */ | 560 | memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */ |
@@ -571,20 +574,19 @@ static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr) | |||
571 | break; | 574 | break; |
572 | } | 575 | } |
573 | 576 | ||
574 | if (stype & IEEE80211_STYPE_QOS_DATA) { | 577 | if (ieee80211_is_data_qos(hdr11->frame_control)) { |
575 | const struct ieee80211_hdr_3addrqos *qoshdr = | 578 | hdr[12] = le16_to_cpu(*ieee80211_get_qos_ctl(hdr11)) |
576 | (struct ieee80211_hdr_3addrqos *)skb->data; | 579 | & IEEE80211_QOS_CTL_TID_MASK; |
577 | hdr[12] = le16_to_cpu(qoshdr->qos_ctl) & IEEE80211_QCTL_TID; | ||
578 | } else | 580 | } else |
579 | hdr[12] = 0; /* priority */ | 581 | hdr[12] = 0; /* priority */ |
580 | 582 | ||
581 | hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */ | 583 | hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */ |
582 | } | 584 | } |
583 | 585 | ||
584 | static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len, | 586 | static int lib80211_michael_mic_add(struct sk_buff *skb, int hdr_len, |
585 | void *priv) | 587 | void *priv) |
586 | { | 588 | { |
587 | struct ieee80211_tkip_data *tkey = priv; | 589 | struct lib80211_tkip_data *tkey = priv; |
588 | u8 *pos; | 590 | u8 *pos; |
589 | 591 | ||
590 | if (skb_tailroom(skb) < 8 || skb->len < hdr_len) { | 592 | if (skb_tailroom(skb) < 8 || skb->len < hdr_len) { |
@@ -603,8 +605,8 @@ static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len, | |||
603 | return 0; | 605 | return 0; |
604 | } | 606 | } |
605 | 607 | ||
606 | static void ieee80211_michael_mic_failure(struct net_device *dev, | 608 | static void lib80211_michael_mic_failure(struct net_device *dev, |
607 | struct ieee80211_hdr_4addr *hdr, | 609 | struct ieee80211_hdr *hdr, |
608 | int keyidx) | 610 | int keyidx) |
609 | { | 611 | { |
610 | union iwreq_data wrqu; | 612 | union iwreq_data wrqu; |
@@ -624,10 +626,10 @@ static void ieee80211_michael_mic_failure(struct net_device *dev, | |||
624 | wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev); | 626 | wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev); |
625 | } | 627 | } |
626 | 628 | ||
627 | static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx, | 629 | static int lib80211_michael_mic_verify(struct sk_buff *skb, int keyidx, |
628 | int hdr_len, void *priv) | 630 | int hdr_len, void *priv) |
629 | { | 631 | { |
630 | struct ieee80211_tkip_data *tkey = priv; | 632 | struct lib80211_tkip_data *tkey = priv; |
631 | u8 mic[8]; | 633 | u8 mic[8]; |
632 | 634 | ||
633 | if (!tkey->key_set) | 635 | if (!tkey->key_set) |
@@ -638,14 +640,14 @@ static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx, | |||
638 | skb->data + hdr_len, skb->len - 8 - hdr_len, mic)) | 640 | skb->data + hdr_len, skb->len - 8 - hdr_len, mic)) |
639 | return -1; | 641 | return -1; |
640 | if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) { | 642 | if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) { |
641 | struct ieee80211_hdr_4addr *hdr; | 643 | struct ieee80211_hdr *hdr; |
642 | hdr = (struct ieee80211_hdr_4addr *)skb->data; | 644 | hdr = (struct ieee80211_hdr *)skb->data; |
643 | printk(KERN_DEBUG "%s: Michael MIC verification failed for " | 645 | printk(KERN_DEBUG "%s: Michael MIC verification failed for " |
644 | "MSDU from %pM keyidx=%d\n", | 646 | "MSDU from %pM keyidx=%d\n", |
645 | skb->dev ? skb->dev->name : "N/A", hdr->addr2, | 647 | skb->dev ? skb->dev->name : "N/A", hdr->addr2, |
646 | keyidx); | 648 | keyidx); |
647 | if (skb->dev) | 649 | if (skb->dev) |
648 | ieee80211_michael_mic_failure(skb->dev, hdr, keyidx); | 650 | lib80211_michael_mic_failure(skb->dev, hdr, keyidx); |
649 | tkey->dot11RSNAStatsTKIPLocalMICFailures++; | 651 | tkey->dot11RSNAStatsTKIPLocalMICFailures++; |
650 | return -1; | 652 | return -1; |
651 | } | 653 | } |
@@ -660,9 +662,9 @@ static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx, | |||
660 | return 0; | 662 | return 0; |
661 | } | 663 | } |
662 | 664 | ||
663 | static int ieee80211_tkip_set_key(void *key, int len, u8 * seq, void *priv) | 665 | static int lib80211_tkip_set_key(void *key, int len, u8 * seq, void *priv) |
664 | { | 666 | { |
665 | struct ieee80211_tkip_data *tkey = priv; | 667 | struct lib80211_tkip_data *tkey = priv; |
666 | int keyidx; | 668 | int keyidx; |
667 | struct crypto_hash *tfm = tkey->tx_tfm_michael; | 669 | struct crypto_hash *tfm = tkey->tx_tfm_michael; |
668 | struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4; | 670 | struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4; |
@@ -693,9 +695,9 @@ static int ieee80211_tkip_set_key(void *key, int len, u8 * seq, void *priv) | |||
693 | return 0; | 695 | return 0; |
694 | } | 696 | } |
695 | 697 | ||
696 | static int ieee80211_tkip_get_key(void *key, int len, u8 * seq, void *priv) | 698 | static int lib80211_tkip_get_key(void *key, int len, u8 * seq, void *priv) |
697 | { | 699 | { |
698 | struct ieee80211_tkip_data *tkey = priv; | 700 | struct lib80211_tkip_data *tkey = priv; |
699 | 701 | ||
700 | if (len < TKIP_KEY_LEN) | 702 | if (len < TKIP_KEY_LEN) |
701 | return -1; | 703 | return -1; |
@@ -722,9 +724,9 @@ static int ieee80211_tkip_get_key(void *key, int len, u8 * seq, void *priv) | |||
722 | return TKIP_KEY_LEN; | 724 | return TKIP_KEY_LEN; |
723 | } | 725 | } |
724 | 726 | ||
725 | static char *ieee80211_tkip_print_stats(char *p, void *priv) | 727 | static char *lib80211_tkip_print_stats(char *p, void *priv) |
726 | { | 728 | { |
727 | struct ieee80211_tkip_data *tkip = priv; | 729 | struct lib80211_tkip_data *tkip = priv; |
728 | p += sprintf(p, "key[%d] alg=TKIP key_set=%d " | 730 | p += sprintf(p, "key[%d] alg=TKIP key_set=%d " |
729 | "tx_pn=%02x%02x%02x%02x%02x%02x " | 731 | "tx_pn=%02x%02x%02x%02x%02x%02x " |
730 | "rx_pn=%02x%02x%02x%02x%02x%02x " | 732 | "rx_pn=%02x%02x%02x%02x%02x%02x " |
@@ -748,35 +750,35 @@ static char *ieee80211_tkip_print_stats(char *p, void *priv) | |||
748 | return p; | 750 | return p; |
749 | } | 751 | } |
750 | 752 | ||
751 | static struct ieee80211_crypto_ops ieee80211_crypt_tkip = { | 753 | static struct lib80211_crypto_ops lib80211_crypt_tkip = { |
752 | .name = "TKIP", | 754 | .name = "TKIP", |
753 | .init = ieee80211_tkip_init, | 755 | .init = lib80211_tkip_init, |
754 | .deinit = ieee80211_tkip_deinit, | 756 | .deinit = lib80211_tkip_deinit, |
755 | .build_iv = ieee80211_tkip_hdr, | 757 | .build_iv = lib80211_tkip_hdr, |
756 | .encrypt_mpdu = ieee80211_tkip_encrypt, | 758 | .encrypt_mpdu = lib80211_tkip_encrypt, |
757 | .decrypt_mpdu = ieee80211_tkip_decrypt, | 759 | .decrypt_mpdu = lib80211_tkip_decrypt, |
758 | .encrypt_msdu = ieee80211_michael_mic_add, | 760 | .encrypt_msdu = lib80211_michael_mic_add, |
759 | .decrypt_msdu = ieee80211_michael_mic_verify, | 761 | .decrypt_msdu = lib80211_michael_mic_verify, |
760 | .set_key = ieee80211_tkip_set_key, | 762 | .set_key = lib80211_tkip_set_key, |
761 | .get_key = ieee80211_tkip_get_key, | 763 | .get_key = lib80211_tkip_get_key, |
762 | .print_stats = ieee80211_tkip_print_stats, | 764 | .print_stats = lib80211_tkip_print_stats, |
763 | .extra_mpdu_prefix_len = 4 + 4, /* IV + ExtIV */ | 765 | .extra_mpdu_prefix_len = 4 + 4, /* IV + ExtIV */ |
764 | .extra_mpdu_postfix_len = 4, /* ICV */ | 766 | .extra_mpdu_postfix_len = 4, /* ICV */ |
765 | .extra_msdu_postfix_len = 8, /* MIC */ | 767 | .extra_msdu_postfix_len = 8, /* MIC */ |
766 | .get_flags = ieee80211_tkip_get_flags, | 768 | .get_flags = lib80211_tkip_get_flags, |
767 | .set_flags = ieee80211_tkip_set_flags, | 769 | .set_flags = lib80211_tkip_set_flags, |
768 | .owner = THIS_MODULE, | 770 | .owner = THIS_MODULE, |
769 | }; | 771 | }; |
770 | 772 | ||
771 | static int __init ieee80211_crypto_tkip_init(void) | 773 | static int __init lib80211_crypto_tkip_init(void) |
772 | { | 774 | { |
773 | return ieee80211_register_crypto_ops(&ieee80211_crypt_tkip); | 775 | return lib80211_register_crypto_ops(&lib80211_crypt_tkip); |
774 | } | 776 | } |
775 | 777 | ||
776 | static void __exit ieee80211_crypto_tkip_exit(void) | 778 | static void __exit lib80211_crypto_tkip_exit(void) |
777 | { | 779 | { |
778 | ieee80211_unregister_crypto_ops(&ieee80211_crypt_tkip); | 780 | lib80211_unregister_crypto_ops(&lib80211_crypt_tkip); |
779 | } | 781 | } |
780 | 782 | ||
781 | module_init(ieee80211_crypto_tkip_init); | 783 | module_init(lib80211_crypto_tkip_init); |
782 | module_exit(ieee80211_crypto_tkip_exit); | 784 | module_exit(lib80211_crypto_tkip_exit); |
diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/wireless/lib80211_crypt_wep.c index 3fa30c40779f..6d41e05ca33b 100644 --- a/net/ieee80211/ieee80211_crypt_wep.c +++ b/net/wireless/lib80211_crypt_wep.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Host AP crypt: host-based WEP encryption implementation for Host AP driver | 2 | * lib80211 crypt: host-based WEP encryption implementation for lib80211 |
3 | * | 3 | * |
4 | * Copyright (c) 2002-2004, Jouni Malinen <j@w1.fi> | 4 | * Copyright (c) 2002-2004, Jouni Malinen <j@w1.fi> |
5 | * Copyright (c) 2008, John W. Linville <linville@tuxdriver.com> | ||
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify | 7 | * 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 | * it under the terms of the GNU General Public License version 2 as |
@@ -19,16 +20,16 @@ | |||
19 | #include <linux/mm.h> | 20 | #include <linux/mm.h> |
20 | #include <asm/string.h> | 21 | #include <asm/string.h> |
21 | 22 | ||
22 | #include <net/ieee80211.h> | 23 | #include <net/lib80211.h> |
23 | 24 | ||
24 | #include <linux/crypto.h> | 25 | #include <linux/crypto.h> |
25 | #include <linux/crc32.h> | 26 | #include <linux/crc32.h> |
26 | 27 | ||
27 | MODULE_AUTHOR("Jouni Malinen"); | 28 | MODULE_AUTHOR("Jouni Malinen"); |
28 | MODULE_DESCRIPTION("Host AP crypt: WEP"); | 29 | MODULE_DESCRIPTION("lib80211 crypt: WEP"); |
29 | MODULE_LICENSE("GPL"); | 30 | MODULE_LICENSE("GPL"); |
30 | 31 | ||
31 | struct prism2_wep_data { | 32 | struct lib80211_wep_data { |
32 | u32 iv; | 33 | u32 iv; |
33 | #define WEP_KEY_LEN 13 | 34 | #define WEP_KEY_LEN 13 |
34 | u8 key[WEP_KEY_LEN + 1]; | 35 | u8 key[WEP_KEY_LEN + 1]; |
@@ -38,9 +39,9 @@ struct prism2_wep_data { | |||
38 | struct crypto_blkcipher *rx_tfm; | 39 | struct crypto_blkcipher *rx_tfm; |
39 | }; | 40 | }; |
40 | 41 | ||
41 | static void *prism2_wep_init(int keyidx) | 42 | static void *lib80211_wep_init(int keyidx) |
42 | { | 43 | { |
43 | struct prism2_wep_data *priv; | 44 | struct lib80211_wep_data *priv; |
44 | 45 | ||
45 | priv = kzalloc(sizeof(*priv), GFP_ATOMIC); | 46 | priv = kzalloc(sizeof(*priv), GFP_ATOMIC); |
46 | if (priv == NULL) | 47 | if (priv == NULL) |
@@ -49,7 +50,7 @@ static void *prism2_wep_init(int keyidx) | |||
49 | 50 | ||
50 | priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); | 51 | priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); |
51 | if (IS_ERR(priv->tx_tfm)) { | 52 | if (IS_ERR(priv->tx_tfm)) { |
52 | printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate " | 53 | printk(KERN_DEBUG "lib80211_crypt_wep: could not allocate " |
53 | "crypto API arc4\n"); | 54 | "crypto API arc4\n"); |
54 | priv->tx_tfm = NULL; | 55 | priv->tx_tfm = NULL; |
55 | goto fail; | 56 | goto fail; |
@@ -57,7 +58,7 @@ static void *prism2_wep_init(int keyidx) | |||
57 | 58 | ||
58 | priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); | 59 | priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); |
59 | if (IS_ERR(priv->rx_tfm)) { | 60 | if (IS_ERR(priv->rx_tfm)) { |
60 | printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate " | 61 | printk(KERN_DEBUG "lib80211_crypt_wep: could not allocate " |
61 | "crypto API arc4\n"); | 62 | "crypto API arc4\n"); |
62 | priv->rx_tfm = NULL; | 63 | priv->rx_tfm = NULL; |
63 | goto fail; | 64 | goto fail; |
@@ -78,9 +79,9 @@ static void *prism2_wep_init(int keyidx) | |||
78 | return NULL; | 79 | return NULL; |
79 | } | 80 | } |
80 | 81 | ||
81 | static void prism2_wep_deinit(void *priv) | 82 | static void lib80211_wep_deinit(void *priv) |
82 | { | 83 | { |
83 | struct prism2_wep_data *_priv = priv; | 84 | struct lib80211_wep_data *_priv = priv; |
84 | if (_priv) { | 85 | if (_priv) { |
85 | if (_priv->tx_tfm) | 86 | if (_priv->tx_tfm) |
86 | crypto_free_blkcipher(_priv->tx_tfm); | 87 | crypto_free_blkcipher(_priv->tx_tfm); |
@@ -91,10 +92,10 @@ static void prism2_wep_deinit(void *priv) | |||
91 | } | 92 | } |
92 | 93 | ||
93 | /* Add WEP IV/key info to a frame that has at least 4 bytes of headroom */ | 94 | /* Add WEP IV/key info to a frame that has at least 4 bytes of headroom */ |
94 | static int prism2_wep_build_iv(struct sk_buff *skb, int hdr_len, | 95 | static int lib80211_wep_build_iv(struct sk_buff *skb, int hdr_len, |
95 | u8 *key, int keylen, void *priv) | 96 | u8 *key, int keylen, void *priv) |
96 | { | 97 | { |
97 | struct prism2_wep_data *wep = priv; | 98 | struct lib80211_wep_data *wep = priv; |
98 | u32 klen, len; | 99 | u32 klen, len; |
99 | u8 *pos; | 100 | u8 *pos; |
100 | 101 | ||
@@ -134,21 +135,21 @@ static int prism2_wep_build_iv(struct sk_buff *skb, int hdr_len, | |||
134 | * | 135 | * |
135 | * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data)) | 136 | * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data)) |
136 | */ | 137 | */ |
137 | static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) | 138 | static int lib80211_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) |
138 | { | 139 | { |
139 | struct prism2_wep_data *wep = priv; | 140 | struct lib80211_wep_data *wep = priv; |
140 | struct blkcipher_desc desc = { .tfm = wep->tx_tfm }; | 141 | struct blkcipher_desc desc = { .tfm = wep->tx_tfm }; |
141 | u32 crc, klen, len; | 142 | u32 crc, klen, len; |
142 | u8 *pos, *icv; | 143 | u8 *pos, *icv; |
143 | struct scatterlist sg; | 144 | struct scatterlist sg; |
144 | u8 key[WEP_KEY_LEN + 3]; | 145 | u8 key[WEP_KEY_LEN + 3]; |
145 | 146 | ||
146 | /* other checks are in prism2_wep_build_iv */ | 147 | /* other checks are in lib80211_wep_build_iv */ |
147 | if (skb_tailroom(skb) < 4) | 148 | if (skb_tailroom(skb) < 4) |
148 | return -1; | 149 | return -1; |
149 | 150 | ||
150 | /* add the IV to the frame */ | 151 | /* add the IV to the frame */ |
151 | if (prism2_wep_build_iv(skb, hdr_len, NULL, 0, priv)) | 152 | if (lib80211_wep_build_iv(skb, hdr_len, NULL, 0, priv)) |
152 | return -1; | 153 | return -1; |
153 | 154 | ||
154 | /* Copy the IV into the first 3 bytes of the key */ | 155 | /* Copy the IV into the first 3 bytes of the key */ |
@@ -181,9 +182,9 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
181 | * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on | 182 | * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on |
182 | * failure. If frame is OK, IV and ICV will be removed. | 183 | * failure. If frame is OK, IV and ICV will be removed. |
183 | */ | 184 | */ |
184 | static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | 185 | static int lib80211_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) |
185 | { | 186 | { |
186 | struct prism2_wep_data *wep = priv; | 187 | struct lib80211_wep_data *wep = priv; |
187 | struct blkcipher_desc desc = { .tfm = wep->rx_tfm }; | 188 | struct blkcipher_desc desc = { .tfm = wep->rx_tfm }; |
188 | u32 crc, klen, plen; | 189 | u32 crc, klen, plen; |
189 | u8 key[WEP_KEY_LEN + 3]; | 190 | u8 key[WEP_KEY_LEN + 3]; |
@@ -232,9 +233,9 @@ static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
232 | return 0; | 233 | return 0; |
233 | } | 234 | } |
234 | 235 | ||
235 | static int prism2_wep_set_key(void *key, int len, u8 * seq, void *priv) | 236 | static int lib80211_wep_set_key(void *key, int len, u8 * seq, void *priv) |
236 | { | 237 | { |
237 | struct prism2_wep_data *wep = priv; | 238 | struct lib80211_wep_data *wep = priv; |
238 | 239 | ||
239 | if (len < 0 || len > WEP_KEY_LEN) | 240 | if (len < 0 || len > WEP_KEY_LEN) |
240 | return -1; | 241 | return -1; |
@@ -245,9 +246,9 @@ static int prism2_wep_set_key(void *key, int len, u8 * seq, void *priv) | |||
245 | return 0; | 246 | return 0; |
246 | } | 247 | } |
247 | 248 | ||
248 | static int prism2_wep_get_key(void *key, int len, u8 * seq, void *priv) | 249 | static int lib80211_wep_get_key(void *key, int len, u8 * seq, void *priv) |
249 | { | 250 | { |
250 | struct prism2_wep_data *wep = priv; | 251 | struct lib80211_wep_data *wep = priv; |
251 | 252 | ||
252 | if (len < wep->key_len) | 253 | if (len < wep->key_len) |
253 | return -1; | 254 | return -1; |
@@ -257,39 +258,39 @@ static int prism2_wep_get_key(void *key, int len, u8 * seq, void *priv) | |||
257 | return wep->key_len; | 258 | return wep->key_len; |
258 | } | 259 | } |
259 | 260 | ||
260 | static char *prism2_wep_print_stats(char *p, void *priv) | 261 | static char *lib80211_wep_print_stats(char *p, void *priv) |
261 | { | 262 | { |
262 | struct prism2_wep_data *wep = priv; | 263 | struct lib80211_wep_data *wep = priv; |
263 | p += sprintf(p, "key[%d] alg=WEP len=%d\n", wep->key_idx, wep->key_len); | 264 | p += sprintf(p, "key[%d] alg=WEP len=%d\n", wep->key_idx, wep->key_len); |
264 | return p; | 265 | return p; |
265 | } | 266 | } |
266 | 267 | ||
267 | static struct ieee80211_crypto_ops ieee80211_crypt_wep = { | 268 | static struct lib80211_crypto_ops lib80211_crypt_wep = { |
268 | .name = "WEP", | 269 | .name = "WEP", |
269 | .init = prism2_wep_init, | 270 | .init = lib80211_wep_init, |
270 | .deinit = prism2_wep_deinit, | 271 | .deinit = lib80211_wep_deinit, |
271 | .build_iv = prism2_wep_build_iv, | 272 | .build_iv = lib80211_wep_build_iv, |
272 | .encrypt_mpdu = prism2_wep_encrypt, | 273 | .encrypt_mpdu = lib80211_wep_encrypt, |
273 | .decrypt_mpdu = prism2_wep_decrypt, | 274 | .decrypt_mpdu = lib80211_wep_decrypt, |
274 | .encrypt_msdu = NULL, | 275 | .encrypt_msdu = NULL, |
275 | .decrypt_msdu = NULL, | 276 | .decrypt_msdu = NULL, |
276 | .set_key = prism2_wep_set_key, | 277 | .set_key = lib80211_wep_set_key, |
277 | .get_key = prism2_wep_get_key, | 278 | .get_key = lib80211_wep_get_key, |
278 | .print_stats = prism2_wep_print_stats, | 279 | .print_stats = lib80211_wep_print_stats, |
279 | .extra_mpdu_prefix_len = 4, /* IV */ | 280 | .extra_mpdu_prefix_len = 4, /* IV */ |
280 | .extra_mpdu_postfix_len = 4, /* ICV */ | 281 | .extra_mpdu_postfix_len = 4, /* ICV */ |
281 | .owner = THIS_MODULE, | 282 | .owner = THIS_MODULE, |
282 | }; | 283 | }; |
283 | 284 | ||
284 | static int __init ieee80211_crypto_wep_init(void) | 285 | static int __init lib80211_crypto_wep_init(void) |
285 | { | 286 | { |
286 | return ieee80211_register_crypto_ops(&ieee80211_crypt_wep); | 287 | return lib80211_register_crypto_ops(&lib80211_crypt_wep); |
287 | } | 288 | } |
288 | 289 | ||
289 | static void __exit ieee80211_crypto_wep_exit(void) | 290 | static void __exit lib80211_crypto_wep_exit(void) |
290 | { | 291 | { |
291 | ieee80211_unregister_crypto_ops(&ieee80211_crypt_wep); | 292 | lib80211_unregister_crypto_ops(&lib80211_crypt_wep); |
292 | } | 293 | } |
293 | 294 | ||
294 | module_init(ieee80211_crypto_wep_init); | 295 | module_init(lib80211_crypto_wep_init); |
295 | module_exit(ieee80211_crypto_wep_exit); | 296 | module_exit(lib80211_crypto_wep_exit); |