1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51#include <linux/netdevice.h>
52#include <linux/wireless.h>
53#include <linux/random.h>
54#include <linux/kernel.h>
55
56
57#include "p80211hdr.h"
58#include "p80211types.h"
59#include "p80211msg.h"
60#include "p80211conv.h"
61#include "p80211netdev.h"
62
63#define WEP_KEY(x) (((x) & 0xC0) >> 6)
64
65static const u32 wep_crc32_table[256] = {
66 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
67 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
68 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
69 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
70 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
71 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
72 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
73 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
74 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
75 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
76 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
77 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
78 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
79 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
80 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
81 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
82 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
83 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
84 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
85 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
86 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
87 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
88 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
89 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
90 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
91 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
92 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
93 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
94 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
95 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
96 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
97 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
98 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
99 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
100 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
101 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
102 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
103 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
104 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
105 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
106 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
107 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
108 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
109 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
110 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
111 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
112 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
113 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
114 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
115 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
116 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
117 0x2d02ef8dL
118};
119
120
121
122int wep_change_key(wlandevice_t *wlandev, int keynum, u8 *key, int keylen)
123{
124 if (keylen < 0)
125 return -1;
126 if (keylen >= MAX_KEYLEN)
127 return -1;
128 if (key == NULL)
129 return -1;
130 if (keynum < 0)
131 return -1;
132 if (keynum >= NUM_WEPKEYS)
133 return -1;
134
135
136 wlandev->wep_keylens[keynum] = keylen;
137 memcpy(wlandev->wep_keys[keynum], key, keylen);
138
139 return 0;
140}
141
142
143
144
145
146int wep_decrypt(wlandevice_t *wlandev, u8 *buf, u32 len, int key_override,
147 u8 *iv, u8 *icv)
148{
149 u32 i, j, k, crc, keylen;
150 u8 s[256], key[64], c_crc[4];
151 u8 keyidx;
152
153
154 if (len <= 0)
155 return -1;
156
157
158 key[0] = iv[0];
159 key[1] = iv[1];
160 key[2] = iv[2];
161 keyidx = WEP_KEY(iv[3]);
162
163 if (key_override >= 0)
164 keyidx = key_override;
165
166 if (keyidx >= NUM_WEPKEYS)
167 return -2;
168
169 keylen = wlandev->wep_keylens[keyidx];
170
171 if (keylen == 0)
172 return -3;
173
174
175 memcpy(key + 3, wlandev->wep_keys[keyidx], keylen);
176
177 keylen += 3;
178
179
180
181 for (i = 0; i < 256; i++)
182 s[i] = i;
183 j = 0;
184 for (i = 0; i < 256; i++) {
185 j = (j + s[i] + key[i % keylen]) & 0xff;
186 swap(i, j);
187 }
188
189
190 crc = ~0;
191 i = j = 0;
192 for (k = 0; k < len; k++) {
193 i = (i + 1) & 0xff;
194 j = (j + s[i]) & 0xff;
195 swap(i, j);
196 buf[k] ^= s[(s[i] + s[j]) & 0xff];
197 crc = wep_crc32_table[(crc ^ buf[k]) & 0xff] ^ (crc >> 8);
198 }
199 crc = ~crc;
200
201
202 c_crc[0] = crc;
203 c_crc[1] = crc >> 8;
204 c_crc[2] = crc >> 16;
205 c_crc[3] = crc >> 24;
206
207 for (k = 0; k < 4; k++) {
208 i = (i + 1) & 0xff;
209 j = (j + s[i]) & 0xff;
210 swap(i, j);
211 if ((c_crc[k] ^ s[(s[i] + s[j]) & 0xff]) != icv[k])
212 return -(4 | (k << 4));
213 }
214
215 return 0;
216}
217
218
219int wep_encrypt(wlandevice_t *wlandev, u8 *buf, u8 *dst, u32 len, int keynum,
220 u8 *iv, u8 *icv)
221{
222 u32 i, j, k, crc, keylen;
223 u8 s[256], key[64];
224
225
226 if (len <= 0)
227 return -1;
228
229
230 if (keynum >= NUM_WEPKEYS)
231 return -2;
232 keylen = wlandev->wep_keylens[keynum];
233 if (keylen <= 0)
234 return -3;
235
236
237 get_random_bytes(iv, 3);
238 while ((iv[1] == 0xff) && (iv[0] >= 3) && (iv[0] < keylen))
239 get_random_bytes(iv, 3);
240
241 iv[3] = (keynum & 0x03) << 6;
242
243 key[0] = iv[0];
244 key[1] = iv[1];
245 key[2] = iv[2];
246
247
248 memcpy(key + 3, wlandev->wep_keys[keynum], keylen);
249
250 keylen += 3;
251
252
253 for (i = 0; i < 256; i++)
254 s[i] = i;
255 j = 0;
256 for (i = 0; i < 256; i++) {
257 j = (j + s[i] + key[i % keylen]) & 0xff;
258 swap(i, j);
259 }
260
261
262 crc = ~0;
263 i = j = 0;
264 for (k = 0; k < len; k++) {
265 crc = wep_crc32_table[(crc ^ buf[k]) & 0xff] ^ (crc >> 8);
266 i = (i + 1) & 0xff;
267 j = (j + s[i]) & 0xff;
268 swap(i, j);
269 dst[k] = buf[k] ^ s[(s[i] + s[j]) & 0xff];
270 }
271 crc = ~crc;
272
273
274 icv[0] = crc;
275 icv[1] = crc >> 8;
276 icv[2] = crc >> 16;
277 icv[3] = crc >> 24;
278
279 for (k = 0; k < 4; k++) {
280 i = (i + 1) & 0xff;
281 j = (j + s[i]) & 0xff;
282 swap(i, j);
283 icv[k] ^= s[(s[i] + s[j]) & 0xff];
284 }
285
286 return 0;
287}
288