aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2008-10-29 11:35:05 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-11-21 11:08:17 -0500
commit274bfb8dc5ffa16cb073801bebe76ab7f4e2e73d (patch)
tree04cd3f6a062496911b56737daa6a0858b769ccd6 /net/wireless
parentdfe1bafdbac1c7b48b636fb7ace799e78170e0d6 (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/wireless')
-rw-r--r--net/wireless/Kconfig9
-rw-r--r--net/wireless/Makefile3
-rw-r--r--net/wireless/lib80211.c191
-rw-r--r--net/wireless/lib80211_crypt_ccmp.c492
-rw-r--r--net/wireless/lib80211_crypt_tkip.c784
-rw-r--r--net/wireless/lib80211_crypt_wep.c296
6 files changed, 1770 insertions, 5 deletions
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
86config LIB80211_CRYPT_WEP
87 tristate
88
89config LIB80211_CRYPT_CCMP
90 tristate
91
92config 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 @@
1obj-$(CONFIG_WIRELESS_EXT) += wext.o 1obj-$(CONFIG_WIRELESS_EXT) += wext.o
2obj-$(CONFIG_CFG80211) += cfg80211.o 2obj-$(CONFIG_CFG80211) += cfg80211.o
3obj-$(CONFIG_LIB80211) += lib80211.o 3obj-$(CONFIG_LIB80211) += lib80211.o
4obj-$(CONFIG_LIB80211_CRYPT_WEP) += lib80211_crypt_wep.o
5obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o
6obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o
4 7
5cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o 8cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o
6cfg80211-$(CONFIG_NL80211) += nl80211.o 9cfg80211-$(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);
19MODULE_AUTHOR("John W. Linville <linville@tuxdriver.com>"); 31MODULE_AUTHOR("John W. Linville <linville@tuxdriver.com>");
20MODULE_LICENSE("GPL"); 32MODULE_LICENSE("GPL");
21 33
34struct lib80211_crypto_alg {
35 struct list_head list;
36 struct lib80211_crypto_ops *ops;
37};
38
39static LIST_HEAD(lib80211_crypto_algs);
40static DEFINE_SPINLOCK(lib80211_crypto_lock);
41
22const char *print_ssid(char *buf, const char *ssid, u8 ssid_len) 42const 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}
52EXPORT_SYMBOL(print_ssid); 72EXPORT_SYMBOL(print_ssid);
53 73
54static int __init ieee80211_init(void) 74void 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}
94EXPORT_SYMBOL(lib80211_crypt_deinit_entries);
95
96/* After this, crypt_deinit_list won't accept new members */
97void 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}
105EXPORT_SYMBOL(lib80211_crypt_quiescing);
106
107void 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}
123EXPORT_SYMBOL(lib80211_crypt_deinit_handler);
124
125void 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}
151EXPORT_SYMBOL(lib80211_crypt_delayed_deinit);
152
153int 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}
173EXPORT_SYMBOL(lib80211_register_crypto_ops);
174
175int 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}
196EXPORT_SYMBOL(lib80211_unregister_crypto_ops);
197
198struct 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}
215EXPORT_SYMBOL(lib80211_get_crypto_ops);
216
217static void *lib80211_crypt_null_init(int keyidx)
218{
219 return (void *)1;
220}
221
222static void lib80211_crypt_null_deinit(void *priv)
223{
224}
225
226static 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
233static 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
60static void __exit ieee80211_exit(void) 239static 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
64module_init(ieee80211_init); 245module_init(lib80211_init);
65module_exit(ieee80211_exit); 246module_exit(lib80211_exit);
diff --git a/net/wireless/lib80211_crypt_ccmp.c b/net/wireless/lib80211_crypt_ccmp.c
new file mode 100644
index 000000000000..db428194c16a
--- /dev/null
+++ b/net/wireless/lib80211_crypt_ccmp.c
@@ -0,0 +1,492 @@
1/*
2 * lib80211 crypt: host-based CCMP encryption implementation for lib80211
3 *
4 * Copyright (c) 2003-2004, Jouni Malinen <j@w1.fi>
5 * Copyright (c) 2008, John W. Linville <linville@tuxdriver.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#include <linux/kernel.h>
14#include <linux/err.h>
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/slab.h>
18#include <linux/random.h>
19#include <linux/skbuff.h>
20#include <linux/netdevice.h>
21#include <linux/if_ether.h>
22#include <linux/if_arp.h>
23#include <asm/string.h>
24#include <linux/wireless.h>
25
26#include <linux/ieee80211.h>
27
28#include <linux/crypto.h>
29
30#include <net/lib80211.h>
31
32MODULE_AUTHOR("Jouni Malinen");
33MODULE_DESCRIPTION("Host AP crypt: CCMP");
34MODULE_LICENSE("GPL");
35
36#define AES_BLOCK_LEN 16
37#define CCMP_HDR_LEN 8
38#define CCMP_MIC_LEN 8
39#define CCMP_TK_LEN 16
40#define CCMP_PN_LEN 6
41
42struct lib80211_ccmp_data {
43 u8 key[CCMP_TK_LEN];
44 int key_set;
45
46 u8 tx_pn[CCMP_PN_LEN];
47 u8 rx_pn[CCMP_PN_LEN];
48
49 u32 dot11RSNAStatsCCMPFormatErrors;
50 u32 dot11RSNAStatsCCMPReplays;
51 u32 dot11RSNAStatsCCMPDecryptErrors;
52
53 int key_idx;
54
55 struct crypto_cipher *tfm;
56
57 /* scratch buffers for virt_to_page() (crypto API) */
58 u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN],
59 tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN];
60 u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN];
61};
62
63static inline void lib80211_ccmp_aes_encrypt(struct crypto_cipher *tfm,
64 const u8 pt[16], u8 ct[16])
65{
66 crypto_cipher_encrypt_one(tfm, ct, pt);
67}
68
69static void *lib80211_ccmp_init(int key_idx)
70{
71 struct lib80211_ccmp_data *priv;
72
73 priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
74 if (priv == NULL)
75 goto fail;
76 priv->key_idx = key_idx;
77
78 priv->tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
79 if (IS_ERR(priv->tfm)) {
80 printk(KERN_DEBUG "lib80211_crypt_ccmp: could not allocate "
81 "crypto API aes\n");
82 priv->tfm = NULL;
83 goto fail;
84 }
85
86 return priv;
87
88 fail:
89 if (priv) {
90 if (priv->tfm)
91 crypto_free_cipher(priv->tfm);
92 kfree(priv);
93 }
94
95 return NULL;
96}
97
98static void lib80211_ccmp_deinit(void *priv)
99{
100 struct lib80211_ccmp_data *_priv = priv;
101 if (_priv && _priv->tfm)
102 crypto_free_cipher(_priv->tfm);
103 kfree(priv);
104}
105
106static inline void xor_block(u8 * b, u8 * a, size_t len)
107{
108 int i;
109 for (i = 0; i < len; i++)
110 b[i] ^= a[i];
111}
112
113static void ccmp_init_blocks(struct crypto_cipher *tfm,
114 struct ieee80211_hdr *hdr,
115 u8 * pn, size_t dlen, u8 * b0, u8 * auth, u8 * s0)
116{
117 u8 *pos, qc = 0;
118 size_t aad_len;
119 int a4_included, qc_included;
120 u8 aad[2 * AES_BLOCK_LEN];
121
122 a4_included = ieee80211_has_a4(hdr->frame_control);
123 qc_included = ieee80211_is_data_qos(hdr->frame_control);
124
125 aad_len = 22;
126 if (a4_included)
127 aad_len += 6;
128 if (qc_included) {
129 pos = (u8 *) & hdr->addr4;
130 if (a4_included)
131 pos += 6;
132 qc = *pos & 0x0f;
133 aad_len += 2;
134 }
135
136 /* CCM Initial Block:
137 * Flag (Include authentication header, M=3 (8-octet MIC),
138 * L=1 (2-octet Dlen))
139 * Nonce: 0x00 | A2 | PN
140 * Dlen */
141 b0[0] = 0x59;
142 b0[1] = qc;
143 memcpy(b0 + 2, hdr->addr2, ETH_ALEN);
144 memcpy(b0 + 8, pn, CCMP_PN_LEN);
145 b0[14] = (dlen >> 8) & 0xff;
146 b0[15] = dlen & 0xff;
147
148 /* AAD:
149 * FC with bits 4..6 and 11..13 masked to zero; 14 is always one
150 * A1 | A2 | A3
151 * SC with bits 4..15 (seq#) masked to zero
152 * A4 (if present)
153 * QC (if present)
154 */
155 pos = (u8 *) hdr;
156 aad[0] = 0; /* aad_len >> 8 */
157 aad[1] = aad_len & 0xff;
158 aad[2] = pos[0] & 0x8f;
159 aad[3] = pos[1] & 0xc7;
160 memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN);
161 pos = (u8 *) & hdr->seq_ctrl;
162 aad[22] = pos[0] & 0x0f;
163 aad[23] = 0; /* all bits masked */
164 memset(aad + 24, 0, 8);
165 if (a4_included)
166 memcpy(aad + 24, hdr->addr4, ETH_ALEN);
167 if (qc_included) {
168 aad[a4_included ? 30 : 24] = qc;
169 /* rest of QC masked */
170 }
171
172 /* Start with the first block and AAD */
173 lib80211_ccmp_aes_encrypt(tfm, b0, auth);
174 xor_block(auth, aad, AES_BLOCK_LEN);
175 lib80211_ccmp_aes_encrypt(tfm, auth, auth);
176 xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN);
177 lib80211_ccmp_aes_encrypt(tfm, auth, auth);
178 b0[0] &= 0x07;
179 b0[14] = b0[15] = 0;
180 lib80211_ccmp_aes_encrypt(tfm, b0, s0);
181}
182
183static int lib80211_ccmp_hdr(struct sk_buff *skb, int hdr_len,
184 u8 *aeskey, int keylen, void *priv)
185{
186 struct lib80211_ccmp_data *key = priv;
187 int i;
188 u8 *pos;
189
190 if (skb_headroom(skb) < CCMP_HDR_LEN || skb->len < hdr_len)
191 return -1;
192
193 if (aeskey != NULL && keylen >= CCMP_TK_LEN)
194 memcpy(aeskey, key->key, CCMP_TK_LEN);
195
196 pos = skb_push(skb, CCMP_HDR_LEN);
197 memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
198 pos += hdr_len;
199
200 i = CCMP_PN_LEN - 1;
201 while (i >= 0) {
202 key->tx_pn[i]++;
203 if (key->tx_pn[i] != 0)
204 break;
205 i--;
206 }
207
208 *pos++ = key->tx_pn[5];
209 *pos++ = key->tx_pn[4];
210 *pos++ = 0;
211 *pos++ = (key->key_idx << 6) | (1 << 5) /* Ext IV included */ ;
212 *pos++ = key->tx_pn[3];
213 *pos++ = key->tx_pn[2];
214 *pos++ = key->tx_pn[1];
215 *pos++ = key->tx_pn[0];
216
217 return CCMP_HDR_LEN;
218}
219
220static int lib80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
221{
222 struct lib80211_ccmp_data *key = priv;
223 int data_len, i, blocks, last, len;
224 u8 *pos, *mic;
225 struct ieee80211_hdr *hdr;
226 u8 *b0 = key->tx_b0;
227 u8 *b = key->tx_b;
228 u8 *e = key->tx_e;
229 u8 *s0 = key->tx_s0;
230
231 if (skb_tailroom(skb) < CCMP_MIC_LEN || skb->len < hdr_len)
232 return -1;
233
234 data_len = skb->len - hdr_len;
235 len = lib80211_ccmp_hdr(skb, hdr_len, NULL, 0, priv);
236 if (len < 0)
237 return -1;
238
239 pos = skb->data + hdr_len + CCMP_HDR_LEN;
240 mic = skb_put(skb, CCMP_MIC_LEN);
241 hdr = (struct ieee80211_hdr *)skb->data;
242 ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0);
243
244 blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN);
245 last = data_len % AES_BLOCK_LEN;
246
247 for (i = 1; i <= blocks; i++) {
248 len = (i == blocks && last) ? last : AES_BLOCK_LEN;
249 /* Authentication */
250 xor_block(b, pos, len);
251 lib80211_ccmp_aes_encrypt(key->tfm, b, b);
252 /* Encryption, with counter */
253 b0[14] = (i >> 8) & 0xff;
254 b0[15] = i & 0xff;
255 lib80211_ccmp_aes_encrypt(key->tfm, b0, e);
256 xor_block(pos, e, len);
257 pos += len;
258 }
259
260 for (i = 0; i < CCMP_MIC_LEN; i++)
261 mic[i] = b[i] ^ s0[i];
262
263 return 0;
264}
265
266/*
267 * deal with seq counter wrapping correctly.
268 * refer to timer_after() for jiffies wrapping handling
269 */
270static inline int ccmp_replay_check(u8 *pn_n, u8 *pn_o)
271{
272 u32 iv32_n, iv16_n;
273 u32 iv32_o, iv16_o;
274
275 iv32_n = (pn_n[0] << 24) | (pn_n[1] << 16) | (pn_n[2] << 8) | pn_n[3];
276 iv16_n = (pn_n[4] << 8) | pn_n[5];
277
278 iv32_o = (pn_o[0] << 24) | (pn_o[1] << 16) | (pn_o[2] << 8) | pn_o[3];
279 iv16_o = (pn_o[4] << 8) | pn_o[5];
280
281 if ((s32)iv32_n - (s32)iv32_o < 0 ||
282 (iv32_n == iv32_o && iv16_n <= iv16_o))
283 return 1;
284 return 0;
285}
286
287static int lib80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
288{
289 struct lib80211_ccmp_data *key = priv;
290 u8 keyidx, *pos;
291 struct ieee80211_hdr *hdr;
292 u8 *b0 = key->rx_b0;
293 u8 *b = key->rx_b;
294 u8 *a = key->rx_a;
295 u8 pn[6];
296 int i, blocks, last, len;
297 size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN - CCMP_MIC_LEN;
298 u8 *mic = skb->data + skb->len - CCMP_MIC_LEN;
299
300 if (skb->len < hdr_len + CCMP_HDR_LEN + CCMP_MIC_LEN) {
301 key->dot11RSNAStatsCCMPFormatErrors++;
302 return -1;
303 }
304
305 hdr = (struct ieee80211_hdr *)skb->data;
306 pos = skb->data + hdr_len;
307 keyidx = pos[3];
308 if (!(keyidx & (1 << 5))) {
309 if (net_ratelimit()) {
310 printk(KERN_DEBUG "CCMP: received packet without ExtIV"
311 " flag from %pM\n", hdr->addr2);
312 }
313 key->dot11RSNAStatsCCMPFormatErrors++;
314 return -2;
315 }
316 keyidx >>= 6;
317 if (key->key_idx != keyidx) {
318 printk(KERN_DEBUG "CCMP: RX tkey->key_idx=%d frame "
319 "keyidx=%d priv=%p\n", key->key_idx, keyidx, priv);
320 return -6;
321 }
322 if (!key->key_set) {
323 if (net_ratelimit()) {
324 printk(KERN_DEBUG "CCMP: received packet from %pM"
325 " with keyid=%d that does not have a configured"
326 " key\n", hdr->addr2, keyidx);
327 }
328 return -3;
329 }
330
331 pn[0] = pos[7];
332 pn[1] = pos[6];
333 pn[2] = pos[5];
334 pn[3] = pos[4];
335 pn[4] = pos[1];
336 pn[5] = pos[0];
337 pos += 8;
338
339 if (ccmp_replay_check(pn, key->rx_pn)) {
340 if (net_ratelimit()) {
341 printk(KERN_DEBUG "CCMP: replay detected: STA=%pM "
342 "previous PN %02x%02x%02x%02x%02x%02x "
343 "received PN %02x%02x%02x%02x%02x%02x\n",
344 hdr->addr2,
345 key->rx_pn[0], key->rx_pn[1], key->rx_pn[2],
346 key->rx_pn[3], key->rx_pn[4], key->rx_pn[5],
347 pn[0], pn[1], pn[2], pn[3], pn[4], pn[5]);
348 }
349 key->dot11RSNAStatsCCMPReplays++;
350 return -4;
351 }
352
353 ccmp_init_blocks(key->tfm, hdr, pn, data_len, b0, a, b);
354 xor_block(mic, b, CCMP_MIC_LEN);
355
356 blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN);
357 last = data_len % AES_BLOCK_LEN;
358
359 for (i = 1; i <= blocks; i++) {
360 len = (i == blocks && last) ? last : AES_BLOCK_LEN;
361 /* Decrypt, with counter */
362 b0[14] = (i >> 8) & 0xff;
363 b0[15] = i & 0xff;
364 lib80211_ccmp_aes_encrypt(key->tfm, b0, b);
365 xor_block(pos, b, len);
366 /* Authentication */
367 xor_block(a, pos, len);
368 lib80211_ccmp_aes_encrypt(key->tfm, a, a);
369 pos += len;
370 }
371
372 if (memcmp(mic, a, CCMP_MIC_LEN) != 0) {
373 if (net_ratelimit()) {
374 printk(KERN_DEBUG "CCMP: decrypt failed: STA="
375 "%pM\n", hdr->addr2);
376 }
377 key->dot11RSNAStatsCCMPDecryptErrors++;
378 return -5;
379 }
380
381 memcpy(key->rx_pn, pn, CCMP_PN_LEN);
382
383 /* Remove hdr and MIC */
384 memmove(skb->data + CCMP_HDR_LEN, skb->data, hdr_len);
385 skb_pull(skb, CCMP_HDR_LEN);
386 skb_trim(skb, skb->len - CCMP_MIC_LEN);
387
388 return keyidx;
389}
390
391static int lib80211_ccmp_set_key(void *key, int len, u8 * seq, void *priv)
392{
393 struct lib80211_ccmp_data *data = priv;
394 int keyidx;
395 struct crypto_cipher *tfm = data->tfm;
396
397 keyidx = data->key_idx;
398 memset(data, 0, sizeof(*data));
399 data->key_idx = keyidx;
400 data->tfm = tfm;
401 if (len == CCMP_TK_LEN) {
402 memcpy(data->key, key, CCMP_TK_LEN);
403 data->key_set = 1;
404 if (seq) {
405 data->rx_pn[0] = seq[5];
406 data->rx_pn[1] = seq[4];
407 data->rx_pn[2] = seq[3];
408 data->rx_pn[3] = seq[2];
409 data->rx_pn[4] = seq[1];
410 data->rx_pn[5] = seq[0];
411 }
412 crypto_cipher_setkey(data->tfm, data->key, CCMP_TK_LEN);
413 } else if (len == 0)
414 data->key_set = 0;
415 else
416 return -1;
417
418 return 0;
419}
420
421static int lib80211_ccmp_get_key(void *key, int len, u8 * seq, void *priv)
422{
423 struct lib80211_ccmp_data *data = priv;
424
425 if (len < CCMP_TK_LEN)
426 return -1;
427
428 if (!data->key_set)
429 return 0;
430 memcpy(key, data->key, CCMP_TK_LEN);
431
432 if (seq) {
433 seq[0] = data->tx_pn[5];
434 seq[1] = data->tx_pn[4];
435 seq[2] = data->tx_pn[3];
436 seq[3] = data->tx_pn[2];
437 seq[4] = data->tx_pn[1];
438 seq[5] = data->tx_pn[0];
439 }
440
441 return CCMP_TK_LEN;
442}
443
444static char *lib80211_ccmp_print_stats(char *p, void *priv)
445{
446 struct lib80211_ccmp_data *ccmp = priv;
447
448 p += sprintf(p, "key[%d] alg=CCMP key_set=%d "
449 "tx_pn=%02x%02x%02x%02x%02x%02x "
450 "rx_pn=%02x%02x%02x%02x%02x%02x "
451 "format_errors=%d replays=%d decrypt_errors=%d\n",
452 ccmp->key_idx, ccmp->key_set,
453 ccmp->tx_pn[0], ccmp->tx_pn[1], ccmp->tx_pn[2],
454 ccmp->tx_pn[3], ccmp->tx_pn[4], ccmp->tx_pn[5],
455 ccmp->rx_pn[0], ccmp->rx_pn[1], ccmp->rx_pn[2],
456 ccmp->rx_pn[3], ccmp->rx_pn[4], ccmp->rx_pn[5],
457 ccmp->dot11RSNAStatsCCMPFormatErrors,
458 ccmp->dot11RSNAStatsCCMPReplays,
459 ccmp->dot11RSNAStatsCCMPDecryptErrors);
460
461 return p;
462}
463
464static struct lib80211_crypto_ops lib80211_crypt_ccmp = {
465 .name = "CCMP",
466 .init = lib80211_ccmp_init,
467 .deinit = lib80211_ccmp_deinit,
468 .build_iv = lib80211_ccmp_hdr,
469 .encrypt_mpdu = lib80211_ccmp_encrypt,
470 .decrypt_mpdu = lib80211_ccmp_decrypt,
471 .encrypt_msdu = NULL,
472 .decrypt_msdu = NULL,
473 .set_key = lib80211_ccmp_set_key,
474 .get_key = lib80211_ccmp_get_key,
475 .print_stats = lib80211_ccmp_print_stats,
476 .extra_mpdu_prefix_len = CCMP_HDR_LEN,
477 .extra_mpdu_postfix_len = CCMP_MIC_LEN,
478 .owner = THIS_MODULE,
479};
480
481static int __init lib80211_crypto_ccmp_init(void)
482{
483 return lib80211_register_crypto_ops(&lib80211_crypt_ccmp);
484}
485
486static void __exit lib80211_crypto_ccmp_exit(void)
487{
488 lib80211_unregister_crypto_ops(&lib80211_crypt_ccmp);
489}
490
491module_init(lib80211_crypto_ccmp_init);
492module_exit(lib80211_crypto_ccmp_exit);
diff --git a/net/wireless/lib80211_crypt_tkip.c b/net/wireless/lib80211_crypt_tkip.c
new file mode 100644
index 000000000000..7e8e22bfed90
--- /dev/null
+++ b/net/wireless/lib80211_crypt_tkip.c
@@ -0,0 +1,784 @@
1/*
2 * lib80211 crypt: host-based TKIP encryption implementation for lib80211
3 *
4 * Copyright (c) 2003-2004, Jouni Malinen <j@w1.fi>
5 * Copyright (c) 2008, John W. Linville <linville@tuxdriver.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#include <linux/err.h>
14#include <linux/module.h>
15#include <linux/init.h>
16#include <linux/slab.h>
17#include <linux/random.h>
18#include <linux/scatterlist.h>
19#include <linux/skbuff.h>
20#include <linux/netdevice.h>
21#include <linux/mm.h>
22#include <linux/if_ether.h>
23#include <linux/if_arp.h>
24#include <asm/string.h>
25
26#include <linux/wireless.h>
27#include <linux/ieee80211.h>
28#include <net/iw_handler.h>
29
30#include <linux/crypto.h>
31#include <linux/crc32.h>
32
33#include <net/lib80211.h>
34
35MODULE_AUTHOR("Jouni Malinen");
36MODULE_DESCRIPTION("lib80211 crypt: TKIP");
37MODULE_LICENSE("GPL");
38
39struct lib80211_tkip_data {
40#define TKIP_KEY_LEN 32
41 u8 key[TKIP_KEY_LEN];
42 int key_set;
43
44 u32 tx_iv32;
45 u16 tx_iv16;
46 u16 tx_ttak[5];
47 int tx_phase1_done;
48
49 u32 rx_iv32;
50 u16 rx_iv16;
51 u16 rx_ttak[5];
52 int rx_phase1_done;
53 u32 rx_iv32_new;
54 u16 rx_iv16_new;
55
56 u32 dot11RSNAStatsTKIPReplays;
57 u32 dot11RSNAStatsTKIPICVErrors;
58 u32 dot11RSNAStatsTKIPLocalMICFailures;
59
60 int key_idx;
61
62 struct crypto_blkcipher *rx_tfm_arc4;
63 struct crypto_hash *rx_tfm_michael;
64 struct crypto_blkcipher *tx_tfm_arc4;
65 struct crypto_hash *tx_tfm_michael;
66
67 /* scratch buffers for virt_to_page() (crypto API) */
68 u8 rx_hdr[16], tx_hdr[16];
69
70 unsigned long flags;
71};
72
73static unsigned long lib80211_tkip_set_flags(unsigned long flags, void *priv)
74{
75 struct lib80211_tkip_data *_priv = priv;
76 unsigned long old_flags = _priv->flags;
77 _priv->flags = flags;
78 return old_flags;
79}
80
81static unsigned long lib80211_tkip_get_flags(void *priv)
82{
83 struct lib80211_tkip_data *_priv = priv;
84 return _priv->flags;
85}
86
87static void *lib80211_tkip_init(int key_idx)
88{
89 struct lib80211_tkip_data *priv;
90
91 priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
92 if (priv == NULL)
93 goto fail;
94
95 priv->key_idx = key_idx;
96
97 priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
98 CRYPTO_ALG_ASYNC);
99 if (IS_ERR(priv->tx_tfm_arc4)) {
100 printk(KERN_DEBUG "lib80211_crypt_tkip: could not allocate "
101 "crypto API arc4\n");
102 priv->tx_tfm_arc4 = NULL;
103 goto fail;
104 }
105
106 priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
107 CRYPTO_ALG_ASYNC);
108 if (IS_ERR(priv->tx_tfm_michael)) {
109 printk(KERN_DEBUG "lib80211_crypt_tkip: could not allocate "
110 "crypto API michael_mic\n");
111 priv->tx_tfm_michael = NULL;
112 goto fail;
113 }
114
115 priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
116 CRYPTO_ALG_ASYNC);
117 if (IS_ERR(priv->rx_tfm_arc4)) {
118 printk(KERN_DEBUG "lib80211_crypt_tkip: could not allocate "
119 "crypto API arc4\n");
120 priv->rx_tfm_arc4 = NULL;
121 goto fail;
122 }
123
124 priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
125 CRYPTO_ALG_ASYNC);
126 if (IS_ERR(priv->rx_tfm_michael)) {
127 printk(KERN_DEBUG "lib80211_crypt_tkip: could not allocate "
128 "crypto API michael_mic\n");
129 priv->rx_tfm_michael = NULL;
130 goto fail;
131 }
132
133 return priv;
134
135 fail:
136 if (priv) {
137 if (priv->tx_tfm_michael)
138 crypto_free_hash(priv->tx_tfm_michael);
139 if (priv->tx_tfm_arc4)
140 crypto_free_blkcipher(priv->tx_tfm_arc4);
141 if (priv->rx_tfm_michael)
142 crypto_free_hash(priv->rx_tfm_michael);
143 if (priv->rx_tfm_arc4)
144 crypto_free_blkcipher(priv->rx_tfm_arc4);
145 kfree(priv);
146 }
147
148 return NULL;
149}
150
151static void lib80211_tkip_deinit(void *priv)
152{
153 struct lib80211_tkip_data *_priv = priv;
154 if (_priv) {
155 if (_priv->tx_tfm_michael)
156 crypto_free_hash(_priv->tx_tfm_michael);
157 if (_priv->tx_tfm_arc4)
158 crypto_free_blkcipher(_priv->tx_tfm_arc4);
159 if (_priv->rx_tfm_michael)
160 crypto_free_hash(_priv->rx_tfm_michael);
161 if (_priv->rx_tfm_arc4)
162 crypto_free_blkcipher(_priv->rx_tfm_arc4);
163 }
164 kfree(priv);
165}
166
167static inline u16 RotR1(u16 val)
168{
169 return (val >> 1) | (val << 15);
170}
171
172static inline u8 Lo8(u16 val)
173{
174 return val & 0xff;
175}
176
177static inline u8 Hi8(u16 val)
178{
179 return val >> 8;
180}
181
182static inline u16 Lo16(u32 val)
183{
184 return val & 0xffff;
185}
186
187static inline u16 Hi16(u32 val)
188{
189 return val >> 16;
190}
191
192static inline u16 Mk16(u8 hi, u8 lo)
193{
194 return lo | (((u16) hi) << 8);
195}
196
197static inline u16 Mk16_le(__le16 * v)
198{
199 return le16_to_cpu(*v);
200}
201
202static const u16 Sbox[256] = {
203 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
204 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
205 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
206 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
207 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
208 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
209 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
210 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
211 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
212 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
213 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
214 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
215 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
216 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
217 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
218 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
219 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
220 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
221 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
222 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
223 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
224 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
225 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
226 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
227 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
228 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
229 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
230 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
231 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
232 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
233 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
234 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
235};
236
237static inline u16 _S_(u16 v)
238{
239 u16 t = Sbox[Hi8(v)];
240 return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8));
241}
242
243#define PHASE1_LOOP_COUNT 8
244
245static void tkip_mixing_phase1(u16 * TTAK, const u8 * TK, const u8 * TA,
246 u32 IV32)
247{
248 int i, j;
249
250 /* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */
251 TTAK[0] = Lo16(IV32);
252 TTAK[1] = Hi16(IV32);
253 TTAK[2] = Mk16(TA[1], TA[0]);
254 TTAK[3] = Mk16(TA[3], TA[2]);
255 TTAK[4] = Mk16(TA[5], TA[4]);
256
257 for (i = 0; i < PHASE1_LOOP_COUNT; i++) {
258 j = 2 * (i & 1);
259 TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j]));
260 TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j]));
261 TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j]));
262 TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j]));
263 TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i;
264 }
265}
266
267static void tkip_mixing_phase2(u8 * WEPSeed, const u8 * TK, const u16 * TTAK,
268 u16 IV16)
269{
270 /* Make temporary area overlap WEP seed so that the final copy can be
271 * avoided on little endian hosts. */
272 u16 *PPK = (u16 *) & WEPSeed[4];
273
274 /* Step 1 - make copy of TTAK and bring in TSC */
275 PPK[0] = TTAK[0];
276 PPK[1] = TTAK[1];
277 PPK[2] = TTAK[2];
278 PPK[3] = TTAK[3];
279 PPK[4] = TTAK[4];
280 PPK[5] = TTAK[4] + IV16;
281
282 /* Step 2 - 96-bit bijective mixing using S-box */
283 PPK[0] += _S_(PPK[5] ^ Mk16_le((__le16 *) & TK[0]));
284 PPK[1] += _S_(PPK[0] ^ Mk16_le((__le16 *) & TK[2]));
285 PPK[2] += _S_(PPK[1] ^ Mk16_le((__le16 *) & TK[4]));
286 PPK[3] += _S_(PPK[2] ^ Mk16_le((__le16 *) & TK[6]));
287 PPK[4] += _S_(PPK[3] ^ Mk16_le((__le16 *) & TK[8]));
288 PPK[5] += _S_(PPK[4] ^ Mk16_le((__le16 *) & TK[10]));
289
290 PPK[0] += RotR1(PPK[5] ^ Mk16_le((__le16 *) & TK[12]));
291 PPK[1] += RotR1(PPK[0] ^ Mk16_le((__le16 *) & TK[14]));
292 PPK[2] += RotR1(PPK[1]);
293 PPK[3] += RotR1(PPK[2]);
294 PPK[4] += RotR1(PPK[3]);
295 PPK[5] += RotR1(PPK[4]);
296
297 /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value
298 * WEPSeed[0..2] is transmitted as WEP IV */
299 WEPSeed[0] = Hi8(IV16);
300 WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F;
301 WEPSeed[2] = Lo8(IV16);
302 WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((__le16 *) & TK[0])) >> 1);
303
304#ifdef __BIG_ENDIAN
305 {
306 int i;
307 for (i = 0; i < 6; i++)
308 PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8);
309 }
310#endif
311}
312
313static int lib80211_tkip_hdr(struct sk_buff *skb, int hdr_len,
314 u8 * rc4key, int keylen, void *priv)
315{
316 struct lib80211_tkip_data *tkey = priv;
317 int len;
318 u8 *pos;
319 struct ieee80211_hdr *hdr;
320
321 hdr = (struct ieee80211_hdr *)skb->data;
322
323 if (skb_headroom(skb) < 8 || skb->len < hdr_len)
324 return -1;
325
326 if (rc4key == NULL || keylen < 16)
327 return -1;
328
329 if (!tkey->tx_phase1_done) {
330 tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
331 tkey->tx_iv32);
332 tkey->tx_phase1_done = 1;
333 }
334 tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);
335
336 len = skb->len - hdr_len;
337 pos = skb_push(skb, 8);
338 memmove(pos, pos + 8, hdr_len);
339 pos += hdr_len;
340
341 *pos++ = *rc4key;
342 *pos++ = *(rc4key + 1);
343 *pos++ = *(rc4key + 2);
344 *pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */ ;
345 *pos++ = tkey->tx_iv32 & 0xff;
346 *pos++ = (tkey->tx_iv32 >> 8) & 0xff;
347 *pos++ = (tkey->tx_iv32 >> 16) & 0xff;
348 *pos++ = (tkey->tx_iv32 >> 24) & 0xff;
349
350 tkey->tx_iv16++;
351 if (tkey->tx_iv16 == 0) {
352 tkey->tx_phase1_done = 0;
353 tkey->tx_iv32++;
354 }
355
356 return 8;
357}
358
359static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
360{
361 struct lib80211_tkip_data *tkey = priv;
362 struct blkcipher_desc desc = { .tfm = tkey->tx_tfm_arc4 };
363 int len;
364 u8 rc4key[16], *pos, *icv;
365 u32 crc;
366 struct scatterlist sg;
367
368 if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
369 if (net_ratelimit()) {
370 struct ieee80211_hdr *hdr =
371 (struct ieee80211_hdr *)skb->data;
372 printk(KERN_DEBUG ": TKIP countermeasures: dropped "
373 "TX packet to %pM\n", hdr->addr1);
374 }
375 return -1;
376 }
377
378 if (skb_tailroom(skb) < 4 || skb->len < hdr_len)
379 return -1;
380
381 len = skb->len - hdr_len;
382 pos = skb->data + hdr_len;
383
384 if ((lib80211_tkip_hdr(skb, hdr_len, rc4key, 16, priv)) < 0)
385 return -1;
386
387 icv = skb_put(skb, 4);
388
389 crc = ~crc32_le(~0, pos, len);
390 icv[0] = crc;
391 icv[1] = crc >> 8;
392 icv[2] = crc >> 16;
393 icv[3] = crc >> 24;
394
395 crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);
396 sg_init_one(&sg, pos, len + 4);
397 return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
398}
399
400/*
401 * deal with seq counter wrapping correctly.
402 * refer to timer_after() for jiffies wrapping handling
403 */
404static inline int tkip_replay_check(u32 iv32_n, u16 iv16_n,
405 u32 iv32_o, u16 iv16_o)
406{
407 if ((s32)iv32_n - (s32)iv32_o < 0 ||
408 (iv32_n == iv32_o && iv16_n <= iv16_o))
409 return 1;
410 return 0;
411}
412
413static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
414{
415 struct lib80211_tkip_data *tkey = priv;
416 struct blkcipher_desc desc = { .tfm = tkey->rx_tfm_arc4 };
417 u8 rc4key[16];
418 u8 keyidx, *pos;
419 u32 iv32;
420 u16 iv16;
421 struct ieee80211_hdr *hdr;
422 u8 icv[4];
423 u32 crc;
424 struct scatterlist sg;
425 int plen;
426
427 hdr = (struct ieee80211_hdr *)skb->data;
428
429 if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
430 if (net_ratelimit()) {
431 printk(KERN_DEBUG ": TKIP countermeasures: dropped "
432 "received packet from %pM\n", hdr->addr2);
433 }
434 return -1;
435 }
436
437 if (skb->len < hdr_len + 8 + 4)
438 return -1;
439
440 pos = skb->data + hdr_len;
441 keyidx = pos[3];
442 if (!(keyidx & (1 << 5))) {
443 if (net_ratelimit()) {
444 printk(KERN_DEBUG "TKIP: received packet without ExtIV"
445 " flag from %pM\n", hdr->addr2);
446 }
447 return -2;
448 }
449 keyidx >>= 6;
450 if (tkey->key_idx != keyidx) {
451 printk(KERN_DEBUG "TKIP: RX tkey->key_idx=%d frame "
452 "keyidx=%d priv=%p\n", tkey->key_idx, keyidx, priv);
453 return -6;
454 }
455 if (!tkey->key_set) {
456 if (net_ratelimit()) {
457 printk(KERN_DEBUG "TKIP: received packet from %pM"
458 " with keyid=%d that does not have a configured"
459 " key\n", hdr->addr2, keyidx);
460 }
461 return -3;
462 }
463 iv16 = (pos[0] << 8) | pos[2];
464 iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
465 pos += 8;
466
467 if (tkip_replay_check(iv32, iv16, tkey->rx_iv32, tkey->rx_iv16)) {
468 if (net_ratelimit()) {
469 printk(KERN_DEBUG "TKIP: replay detected: STA=%pM"
470 " previous TSC %08x%04x received TSC "
471 "%08x%04x\n", hdr->addr2,
472 tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
473 }
474 tkey->dot11RSNAStatsTKIPReplays++;
475 return -4;
476 }
477
478 if (iv32 != tkey->rx_iv32 || !tkey->rx_phase1_done) {
479 tkip_mixing_phase1(tkey->rx_ttak, tkey->key, hdr->addr2, iv32);
480 tkey->rx_phase1_done = 1;
481 }
482 tkip_mixing_phase2(rc4key, tkey->key, tkey->rx_ttak, iv16);
483
484 plen = skb->len - hdr_len - 12;
485
486 crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
487 sg_init_one(&sg, pos, plen + 4);
488 if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) {
489 if (net_ratelimit()) {
490 printk(KERN_DEBUG ": TKIP: failed to decrypt "
491 "received packet from %pM\n",
492 hdr->addr2);
493 }
494 return -7;
495 }
496
497 crc = ~crc32_le(~0, pos, plen);
498 icv[0] = crc;
499 icv[1] = crc >> 8;
500 icv[2] = crc >> 16;
501 icv[3] = crc >> 24;
502 if (memcmp(icv, pos + plen, 4) != 0) {
503 if (iv32 != tkey->rx_iv32) {
504 /* Previously cached Phase1 result was already lost, so
505 * it needs to be recalculated for the next packet. */
506 tkey->rx_phase1_done = 0;
507 }
508 if (net_ratelimit()) {
509 printk(KERN_DEBUG "TKIP: ICV error detected: STA="
510 "%pM\n", hdr->addr2);
511 }
512 tkey->dot11RSNAStatsTKIPICVErrors++;
513 return -5;
514 }
515
516 /* Update real counters only after Michael MIC verification has
517 * completed */
518 tkey->rx_iv32_new = iv32;
519 tkey->rx_iv16_new = iv16;
520
521 /* Remove IV and ICV */
522 memmove(skb->data + 8, skb->data, hdr_len);
523 skb_pull(skb, 8);
524 skb_trim(skb, skb->len - 4);
525
526 return keyidx;
527}
528
529static int michael_mic(struct crypto_hash *tfm_michael, u8 * key, u8 * hdr,
530 u8 * data, size_t data_len, u8 * mic)
531{
532 struct hash_desc desc;
533 struct scatterlist sg[2];
534
535 if (tfm_michael == NULL) {
536 printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
537 return -1;
538 }
539 sg_init_table(sg, 2);
540 sg_set_buf(&sg[0], hdr, 16);
541 sg_set_buf(&sg[1], data, data_len);
542
543 if (crypto_hash_setkey(tfm_michael, key, 8))
544 return -1;
545
546 desc.tfm = tfm_michael;
547 desc.flags = 0;
548 return crypto_hash_digest(&desc, sg, data_len + 16, mic);
549}
550
551static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
552{
553 struct ieee80211_hdr *hdr11;
554
555 hdr11 = (struct ieee80211_hdr *)skb->data;
556
557 switch (le16_to_cpu(hdr11->frame_control) &
558 (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
559 case IEEE80211_FCTL_TODS:
560 memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
561 memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
562 break;
563 case IEEE80211_FCTL_FROMDS:
564 memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
565 memcpy(hdr + ETH_ALEN, hdr11->addr3, ETH_ALEN); /* SA */
566 break;
567 case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
568 memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
569 memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */
570 break;
571 case 0:
572 memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
573 memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
574 break;
575 }
576
577 if (ieee80211_is_data_qos(hdr11->frame_control)) {
578 hdr[12] = le16_to_cpu(*ieee80211_get_qos_ctl(hdr11))
579 & IEEE80211_QOS_CTL_TID_MASK;
580 } else
581 hdr[12] = 0; /* priority */
582
583 hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */
584}
585
586static int lib80211_michael_mic_add(struct sk_buff *skb, int hdr_len,
587 void *priv)
588{
589 struct lib80211_tkip_data *tkey = priv;
590 u8 *pos;
591
592 if (skb_tailroom(skb) < 8 || skb->len < hdr_len) {
593 printk(KERN_DEBUG "Invalid packet for Michael MIC add "
594 "(tailroom=%d hdr_len=%d skb->len=%d)\n",
595 skb_tailroom(skb), hdr_len, skb->len);
596 return -1;
597 }
598
599 michael_mic_hdr(skb, tkey->tx_hdr);
600 pos = skb_put(skb, 8);
601 if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr,
602 skb->data + hdr_len, skb->len - 8 - hdr_len, pos))
603 return -1;
604
605 return 0;
606}
607
608static void lib80211_michael_mic_failure(struct net_device *dev,
609 struct ieee80211_hdr *hdr,
610 int keyidx)
611{
612 union iwreq_data wrqu;
613 struct iw_michaelmicfailure ev;
614
615 /* TODO: needed parameters: count, keyid, key type, TSC */
616 memset(&ev, 0, sizeof(ev));
617 ev.flags = keyidx & IW_MICFAILURE_KEY_ID;
618 if (hdr->addr1[0] & 0x01)
619 ev.flags |= IW_MICFAILURE_GROUP;
620 else
621 ev.flags |= IW_MICFAILURE_PAIRWISE;
622 ev.src_addr.sa_family = ARPHRD_ETHER;
623 memcpy(ev.src_addr.sa_data, hdr->addr2, ETH_ALEN);
624 memset(&wrqu, 0, sizeof(wrqu));
625 wrqu.data.length = sizeof(ev);
626 wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev);
627}
628
629static int lib80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
630 int hdr_len, void *priv)
631{
632 struct lib80211_tkip_data *tkey = priv;
633 u8 mic[8];
634
635 if (!tkey->key_set)
636 return -1;
637
638 michael_mic_hdr(skb, tkey->rx_hdr);
639 if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr,
640 skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
641 return -1;
642 if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
643 struct ieee80211_hdr *hdr;
644 hdr = (struct ieee80211_hdr *)skb->data;
645 printk(KERN_DEBUG "%s: Michael MIC verification failed for "
646 "MSDU from %pM keyidx=%d\n",
647 skb->dev ? skb->dev->name : "N/A", hdr->addr2,
648 keyidx);
649 if (skb->dev)
650 lib80211_michael_mic_failure(skb->dev, hdr, keyidx);
651 tkey->dot11RSNAStatsTKIPLocalMICFailures++;
652 return -1;
653 }
654
655 /* Update TSC counters for RX now that the packet verification has
656 * completed. */
657 tkey->rx_iv32 = tkey->rx_iv32_new;
658 tkey->rx_iv16 = tkey->rx_iv16_new;
659
660 skb_trim(skb, skb->len - 8);
661
662 return 0;
663}
664
665static int lib80211_tkip_set_key(void *key, int len, u8 * seq, void *priv)
666{
667 struct lib80211_tkip_data *tkey = priv;
668 int keyidx;
669 struct crypto_hash *tfm = tkey->tx_tfm_michael;
670 struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4;
671 struct crypto_hash *tfm3 = tkey->rx_tfm_michael;
672 struct crypto_blkcipher *tfm4 = tkey->rx_tfm_arc4;
673
674 keyidx = tkey->key_idx;
675 memset(tkey, 0, sizeof(*tkey));
676 tkey->key_idx = keyidx;
677 tkey->tx_tfm_michael = tfm;
678 tkey->tx_tfm_arc4 = tfm2;
679 tkey->rx_tfm_michael = tfm3;
680 tkey->rx_tfm_arc4 = tfm4;
681 if (len == TKIP_KEY_LEN) {
682 memcpy(tkey->key, key, TKIP_KEY_LEN);
683 tkey->key_set = 1;
684 tkey->tx_iv16 = 1; /* TSC is initialized to 1 */
685 if (seq) {
686 tkey->rx_iv32 = (seq[5] << 24) | (seq[4] << 16) |
687 (seq[3] << 8) | seq[2];
688 tkey->rx_iv16 = (seq[1] << 8) | seq[0];
689 }
690 } else if (len == 0)
691 tkey->key_set = 0;
692 else
693 return -1;
694
695 return 0;
696}
697
698static int lib80211_tkip_get_key(void *key, int len, u8 * seq, void *priv)
699{
700 struct lib80211_tkip_data *tkey = priv;
701
702 if (len < TKIP_KEY_LEN)
703 return -1;
704
705 if (!tkey->key_set)
706 return 0;
707 memcpy(key, tkey->key, TKIP_KEY_LEN);
708
709 if (seq) {
710 /* Return the sequence number of the last transmitted frame. */
711 u16 iv16 = tkey->tx_iv16;
712 u32 iv32 = tkey->tx_iv32;
713 if (iv16 == 0)
714 iv32--;
715 iv16--;
716 seq[0] = tkey->tx_iv16;
717 seq[1] = tkey->tx_iv16 >> 8;
718 seq[2] = tkey->tx_iv32;
719 seq[3] = tkey->tx_iv32 >> 8;
720 seq[4] = tkey->tx_iv32 >> 16;
721 seq[5] = tkey->tx_iv32 >> 24;
722 }
723
724 return TKIP_KEY_LEN;
725}
726
727static char *lib80211_tkip_print_stats(char *p, void *priv)
728{
729 struct lib80211_tkip_data *tkip = priv;
730 p += sprintf(p, "key[%d] alg=TKIP key_set=%d "
731 "tx_pn=%02x%02x%02x%02x%02x%02x "
732 "rx_pn=%02x%02x%02x%02x%02x%02x "
733 "replays=%d icv_errors=%d local_mic_failures=%d\n",
734 tkip->key_idx, tkip->key_set,
735 (tkip->tx_iv32 >> 24) & 0xff,
736 (tkip->tx_iv32 >> 16) & 0xff,
737 (tkip->tx_iv32 >> 8) & 0xff,
738 tkip->tx_iv32 & 0xff,
739 (tkip->tx_iv16 >> 8) & 0xff,
740 tkip->tx_iv16 & 0xff,
741 (tkip->rx_iv32 >> 24) & 0xff,
742 (tkip->rx_iv32 >> 16) & 0xff,
743 (tkip->rx_iv32 >> 8) & 0xff,
744 tkip->rx_iv32 & 0xff,
745 (tkip->rx_iv16 >> 8) & 0xff,
746 tkip->rx_iv16 & 0xff,
747 tkip->dot11RSNAStatsTKIPReplays,
748 tkip->dot11RSNAStatsTKIPICVErrors,
749 tkip->dot11RSNAStatsTKIPLocalMICFailures);
750 return p;
751}
752
753static struct lib80211_crypto_ops lib80211_crypt_tkip = {
754 .name = "TKIP",
755 .init = lib80211_tkip_init,
756 .deinit = lib80211_tkip_deinit,
757 .build_iv = lib80211_tkip_hdr,
758 .encrypt_mpdu = lib80211_tkip_encrypt,
759 .decrypt_mpdu = lib80211_tkip_decrypt,
760 .encrypt_msdu = lib80211_michael_mic_add,
761 .decrypt_msdu = lib80211_michael_mic_verify,
762 .set_key = lib80211_tkip_set_key,
763 .get_key = lib80211_tkip_get_key,
764 .print_stats = lib80211_tkip_print_stats,
765 .extra_mpdu_prefix_len = 4 + 4, /* IV + ExtIV */
766 .extra_mpdu_postfix_len = 4, /* ICV */
767 .extra_msdu_postfix_len = 8, /* MIC */
768 .get_flags = lib80211_tkip_get_flags,
769 .set_flags = lib80211_tkip_set_flags,
770 .owner = THIS_MODULE,
771};
772
773static int __init lib80211_crypto_tkip_init(void)
774{
775 return lib80211_register_crypto_ops(&lib80211_crypt_tkip);
776}
777
778static void __exit lib80211_crypto_tkip_exit(void)
779{
780 lib80211_unregister_crypto_ops(&lib80211_crypt_tkip);
781}
782
783module_init(lib80211_crypto_tkip_init);
784module_exit(lib80211_crypto_tkip_exit);
diff --git a/net/wireless/lib80211_crypt_wep.c b/net/wireless/lib80211_crypt_wep.c
new file mode 100644
index 000000000000..6d41e05ca33b
--- /dev/null
+++ b/net/wireless/lib80211_crypt_wep.c
@@ -0,0 +1,296 @@
1/*
2 * lib80211 crypt: host-based WEP encryption implementation for lib80211
3 *
4 * Copyright (c) 2002-2004, Jouni Malinen <j@w1.fi>
5 * Copyright (c) 2008, John W. Linville <linville@tuxdriver.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#include <linux/err.h>
14#include <linux/module.h>
15#include <linux/init.h>
16#include <linux/slab.h>
17#include <linux/random.h>
18#include <linux/scatterlist.h>
19#include <linux/skbuff.h>
20#include <linux/mm.h>
21#include <asm/string.h>
22
23#include <net/lib80211.h>
24
25#include <linux/crypto.h>
26#include <linux/crc32.h>
27
28MODULE_AUTHOR("Jouni Malinen");
29MODULE_DESCRIPTION("lib80211 crypt: WEP");
30MODULE_LICENSE("GPL");
31
32struct lib80211_wep_data {
33 u32 iv;
34#define WEP_KEY_LEN 13
35 u8 key[WEP_KEY_LEN + 1];
36 u8 key_len;
37 u8 key_idx;
38 struct crypto_blkcipher *tx_tfm;
39 struct crypto_blkcipher *rx_tfm;
40};
41
42static void *lib80211_wep_init(int keyidx)
43{
44 struct lib80211_wep_data *priv;
45
46 priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
47 if (priv == NULL)
48 goto fail;
49 priv->key_idx = keyidx;
50
51 priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
52 if (IS_ERR(priv->tx_tfm)) {
53 printk(KERN_DEBUG "lib80211_crypt_wep: could not allocate "
54 "crypto API arc4\n");
55 priv->tx_tfm = NULL;
56 goto fail;
57 }
58
59 priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
60 if (IS_ERR(priv->rx_tfm)) {
61 printk(KERN_DEBUG "lib80211_crypt_wep: could not allocate "
62 "crypto API arc4\n");
63 priv->rx_tfm = NULL;
64 goto fail;
65 }
66 /* start WEP IV from a random value */
67 get_random_bytes(&priv->iv, 4);
68
69 return priv;
70
71 fail:
72 if (priv) {
73 if (priv->tx_tfm)
74 crypto_free_blkcipher(priv->tx_tfm);
75 if (priv->rx_tfm)
76 crypto_free_blkcipher(priv->rx_tfm);
77 kfree(priv);
78 }
79 return NULL;
80}
81
82static void lib80211_wep_deinit(void *priv)
83{
84 struct lib80211_wep_data *_priv = priv;
85 if (_priv) {
86 if (_priv->tx_tfm)
87 crypto_free_blkcipher(_priv->tx_tfm);
88 if (_priv->rx_tfm)
89 crypto_free_blkcipher(_priv->rx_tfm);
90 }
91 kfree(priv);
92}
93
94/* Add WEP IV/key info to a frame that has at least 4 bytes of headroom */
95static int lib80211_wep_build_iv(struct sk_buff *skb, int hdr_len,
96 u8 *key, int keylen, void *priv)
97{
98 struct lib80211_wep_data *wep = priv;
99 u32 klen, len;
100 u8 *pos;
101
102 if (skb_headroom(skb) < 4 || skb->len < hdr_len)
103 return -1;
104
105 len = skb->len - hdr_len;
106 pos = skb_push(skb, 4);
107 memmove(pos, pos + 4, hdr_len);
108 pos += hdr_len;
109
110 klen = 3 + wep->key_len;
111
112 wep->iv++;
113
114 /* Fluhrer, Mantin, and Shamir have reported weaknesses in the key
115 * scheduling algorithm of RC4. At least IVs (KeyByte + 3, 0xff, N)
116 * can be used to speedup attacks, so avoid using them. */
117 if ((wep->iv & 0xff00) == 0xff00) {
118 u8 B = (wep->iv >> 16) & 0xff;
119 if (B >= 3 && B < klen)
120 wep->iv += 0x0100;
121 }
122
123 /* Prepend 24-bit IV to RC4 key and TX frame */
124 *pos++ = (wep->iv >> 16) & 0xff;
125 *pos++ = (wep->iv >> 8) & 0xff;
126 *pos++ = wep->iv & 0xff;
127 *pos++ = wep->key_idx << 6;
128
129 return 0;
130}
131
132/* Perform WEP encryption on given skb that has at least 4 bytes of headroom
133 * for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted,
134 * so the payload length increases with 8 bytes.
135 *
136 * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
137 */
138static int lib80211_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
139{
140 struct lib80211_wep_data *wep = priv;
141 struct blkcipher_desc desc = { .tfm = wep->tx_tfm };
142 u32 crc, klen, len;
143 u8 *pos, *icv;
144 struct scatterlist sg;
145 u8 key[WEP_KEY_LEN + 3];
146
147 /* other checks are in lib80211_wep_build_iv */
148 if (skb_tailroom(skb) < 4)
149 return -1;
150
151 /* add the IV to the frame */
152 if (lib80211_wep_build_iv(skb, hdr_len, NULL, 0, priv))
153 return -1;
154
155 /* Copy the IV into the first 3 bytes of the key */
156 skb_copy_from_linear_data_offset(skb, hdr_len, key, 3);
157
158 /* Copy rest of the WEP key (the secret part) */
159 memcpy(key + 3, wep->key, wep->key_len);
160
161 len = skb->len - hdr_len - 4;
162 pos = skb->data + hdr_len + 4;
163 klen = 3 + wep->key_len;
164
165 /* Append little-endian CRC32 over only the data and encrypt it to produce ICV */
166 crc = ~crc32_le(~0, pos, len);
167 icv = skb_put(skb, 4);
168 icv[0] = crc;
169 icv[1] = crc >> 8;
170 icv[2] = crc >> 16;
171 icv[3] = crc >> 24;
172
173 crypto_blkcipher_setkey(wep->tx_tfm, key, klen);
174 sg_init_one(&sg, pos, len + 4);
175 return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
176}
177
178/* Perform WEP decryption on given buffer. Buffer includes whole WEP part of
179 * the frame: IV (4 bytes), encrypted payload (including SNAP header),
180 * ICV (4 bytes). len includes both IV and ICV.
181 *
182 * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on
183 * failure. If frame is OK, IV and ICV will be removed.
184 */
185static int lib80211_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
186{
187 struct lib80211_wep_data *wep = priv;
188 struct blkcipher_desc desc = { .tfm = wep->rx_tfm };
189 u32 crc, klen, plen;
190 u8 key[WEP_KEY_LEN + 3];
191 u8 keyidx, *pos, icv[4];
192 struct scatterlist sg;
193
194 if (skb->len < hdr_len + 8)
195 return -1;
196
197 pos = skb->data + hdr_len;
198 key[0] = *pos++;
199 key[1] = *pos++;
200 key[2] = *pos++;
201 keyidx = *pos++ >> 6;
202 if (keyidx != wep->key_idx)
203 return -1;
204
205 klen = 3 + wep->key_len;
206
207 /* Copy rest of the WEP key (the secret part) */
208 memcpy(key + 3, wep->key, wep->key_len);
209
210 /* Apply RC4 to data and compute CRC32 over decrypted data */
211 plen = skb->len - hdr_len - 8;
212
213 crypto_blkcipher_setkey(wep->rx_tfm, key, klen);
214 sg_init_one(&sg, pos, plen + 4);
215 if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4))
216 return -7;
217
218 crc = ~crc32_le(~0, pos, plen);
219 icv[0] = crc;
220 icv[1] = crc >> 8;
221 icv[2] = crc >> 16;
222 icv[3] = crc >> 24;
223 if (memcmp(icv, pos + plen, 4) != 0) {
224 /* ICV mismatch - drop frame */
225 return -2;
226 }
227
228 /* Remove IV and ICV */
229 memmove(skb->data + 4, skb->data, hdr_len);
230 skb_pull(skb, 4);
231 skb_trim(skb, skb->len - 4);
232
233 return 0;
234}
235
236static int lib80211_wep_set_key(void *key, int len, u8 * seq, void *priv)
237{
238 struct lib80211_wep_data *wep = priv;
239
240 if (len < 0 || len > WEP_KEY_LEN)
241 return -1;
242
243 memcpy(wep->key, key, len);
244 wep->key_len = len;
245
246 return 0;
247}
248
249static int lib80211_wep_get_key(void *key, int len, u8 * seq, void *priv)
250{
251 struct lib80211_wep_data *wep = priv;
252
253 if (len < wep->key_len)
254 return -1;
255
256 memcpy(key, wep->key, wep->key_len);
257
258 return wep->key_len;
259}
260
261static char *lib80211_wep_print_stats(char *p, void *priv)
262{
263 struct lib80211_wep_data *wep = priv;
264 p += sprintf(p, "key[%d] alg=WEP len=%d\n", wep->key_idx, wep->key_len);
265 return p;
266}
267
268static struct lib80211_crypto_ops lib80211_crypt_wep = {
269 .name = "WEP",
270 .init = lib80211_wep_init,
271 .deinit = lib80211_wep_deinit,
272 .build_iv = lib80211_wep_build_iv,
273 .encrypt_mpdu = lib80211_wep_encrypt,
274 .decrypt_mpdu = lib80211_wep_decrypt,
275 .encrypt_msdu = NULL,
276 .decrypt_msdu = NULL,
277 .set_key = lib80211_wep_set_key,
278 .get_key = lib80211_wep_get_key,
279 .print_stats = lib80211_wep_print_stats,
280 .extra_mpdu_prefix_len = 4, /* IV */
281 .extra_mpdu_postfix_len = 4, /* ICV */
282 .owner = THIS_MODULE,
283};
284
285static int __init lib80211_crypto_wep_init(void)
286{
287 return lib80211_register_crypto_ops(&lib80211_crypt_wep);
288}
289
290static void __exit lib80211_crypto_wep_exit(void)
291{
292 lib80211_unregister_crypto_ops(&lib80211_crypt_wep);
293}
294
295module_init(lib80211_crypto_wep_init);
296module_exit(lib80211_crypto_wep_exit);