Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
p80211wep.c
Go to the documentation of this file.
1 /* src/p80211/p80211wep.c
2 *
3 * WEP encode/decode for P80211.
4 *
5 * Copyright (C) 2002 AbsoluteValue Systems, Inc. All Rights Reserved.
6 * --------------------------------------------------------------------
7 *
8 * linux-wlan
9 *
10 * The contents of this file are subject to the Mozilla Public
11 * License Version 1.1 (the "License"); you may not use this file
12 * except in compliance with the License. You may obtain a copy of
13 * the License at http://www.mozilla.org/MPL/
14 *
15 * Software distributed under the License is distributed on an "AS
16 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
17 * implied. See the License for the specific language governing
18 * rights and limitations under the License.
19 *
20 * Alternatively, the contents of this file may be used under the
21 * terms of the GNU Public License version 2 (the "GPL"), in which
22 * case the provisions of the GPL are applicable instead of the
23 * above. If you wish to allow the use of your version of this file
24 * only under the terms of the GPL and not to allow others to use
25 * your version of this file under the MPL, indicate your decision
26 * by deleting the provisions above and replace them with the notice
27 * and other provisions required by the GPL. If you do not delete
28 * the provisions above, a recipient may use your version of this
29 * file under either the MPL or the GPL.
30 *
31 * --------------------------------------------------------------------
32 *
33 * Inquiries regarding the linux-wlan Open Source project can be
34 * made directly to:
35 *
36 * AbsoluteValue Systems Inc.
38 * http://www.linux-wlan.com
39 *
40 * --------------------------------------------------------------------
41 *
42 * Portions of the development of this software were funded by
43 * Intersil Corporation as part of PRISM(R) chipset product development.
44 *
45 * --------------------------------------------------------------------
46 */
47 
48 /*================================================================*/
49 /* System Includes */
50 
51 #include <linux/netdevice.h>
52 #include <linux/wireless.h>
53 #include <linux/random.h>
54 #include <linux/kernel.h>
55 
56 /* #define WEP_DEBUG */
57 
58 #include "p80211hdr.h"
59 #include "p80211types.h"
60 #include "p80211msg.h"
61 #include "p80211conv.h"
62 #include "p80211netdev.h"
63 
64 #define WEP_KEY(x) (((x) & 0xC0) >> 6)
65 
66 static const u32 wep_crc32_table[256] = {
67  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
68  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
69  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
70  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
71  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
72  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
73  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
74  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
75  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
76  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
77  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
78  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
79  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
80  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
81  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
82  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
83  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
84  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
85  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
86  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
87  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
88  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
89  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
90  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
91  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
92  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
93  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
94  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
95  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
96  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
97  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
98  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
99  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
100  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
101  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
102  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
103  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
104  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
105  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
106  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
107  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
108  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
109  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
110  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
111  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
112  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
113  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
114  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
115  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
116  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
117  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
118  0x2d02ef8dL
119 };
120 
121 /* keylen in bytes! */
122 
123 int wep_change_key(wlandevice_t *wlandev, int keynum, u8 *key, int keylen)
124 {
125  if (keylen < 0)
126  return -1;
127  if (keylen >= MAX_KEYLEN)
128  return -1;
129  if (key == NULL)
130  return -1;
131  if (keynum < 0)
132  return -1;
133  if (keynum >= NUM_WEPKEYS)
134  return -1;
135 
136 #ifdef WEP_DEBUG
137  printk(KERN_DEBUG "WEP key %d len %d = %*phC\n", keynum, keylen,
138  8, key);
139 #endif
140 
141  wlandev->wep_keylens[keynum] = keylen;
142  memcpy(wlandev->wep_keys[keynum], key, keylen);
143 
144  return 0;
145 }
146 
147 /*
148  4-byte IV at start of buffer, 4-byte ICV at end of buffer.
149  if successful, buf start is payload begin, length -= 8;
150  */
151 int wep_decrypt(wlandevice_t *wlandev, u8 *buf, u32 len, int key_override,
152  u8 *iv, u8 *icv)
153 {
154  u32 i, j, k, crc, keylen;
155  u8 s[256], key[64], c_crc[4];
156  u8 keyidx;
157 
158  /* Needs to be at least 8 bytes of payload */
159  if (len <= 0)
160  return -1;
161 
162  /* initialize the first bytes of the key from the IV */
163  key[0] = iv[0];
164  key[1] = iv[1];
165  key[2] = iv[2];
166  keyidx = WEP_KEY(iv[3]);
167 
168  if (key_override >= 0)
169  keyidx = key_override;
170 
171  if (keyidx >= NUM_WEPKEYS)
172  return -2;
173 
174  keylen = wlandev->wep_keylens[keyidx];
175 
176  if (keylen == 0)
177  return -3;
178 
179  /* copy the rest of the key over from the designated key */
180  memcpy(key + 3, wlandev->wep_keys[keyidx], keylen);
181 
182  keylen += 3; /* add in IV bytes */
183 
184 #ifdef WEP_DEBUG
185  printk(KERN_DEBUG "D %d: %*ph (%d %d) %*phC\n", len, 3, key,
186  keyidx, keylen, 5, key + 3);
187 #endif
188 
189  /* set up the RC4 state */
190  for (i = 0; i < 256; i++)
191  s[i] = i;
192  j = 0;
193  for (i = 0; i < 256; i++) {
194  j = (j + s[i] + key[i % keylen]) & 0xff;
195  swap(i, j);
196  }
197 
198  /* Apply the RC4 to the data, update the CRC32 */
199  crc = ~0;
200  i = j = 0;
201  for (k = 0; k < len; k++) {
202  i = (i + 1) & 0xff;
203  j = (j + s[i]) & 0xff;
204  swap(i, j);
205  buf[k] ^= s[(s[i] + s[j]) & 0xff];
206  crc = wep_crc32_table[(crc ^ buf[k]) & 0xff] ^ (crc >> 8);
207  }
208  crc = ~crc;
209 
210  /* now let's check the crc */
211  c_crc[0] = crc;
212  c_crc[1] = crc >> 8;
213  c_crc[2] = crc >> 16;
214  c_crc[3] = crc >> 24;
215 
216  for (k = 0; k < 4; k++) {
217  i = (i + 1) & 0xff;
218  j = (j + s[i]) & 0xff;
219  swap(i, j);
220  if ((c_crc[k] ^ s[(s[i] + s[j]) & 0xff]) != icv[k])
221  return -(4 | (k << 4)); /* ICV mismatch */
222  }
223 
224  return 0;
225 }
226 
227 /* encrypts in-place. */
228 int wep_encrypt(wlandevice_t *wlandev, u8 *buf, u8 *dst, u32 len, int keynum,
229  u8 *iv, u8 *icv)
230 {
231  u32 i, j, k, crc, keylen;
232  u8 s[256], key[64];
233 
234  /* no point in WEPping an empty frame */
235  if (len <= 0)
236  return -1;
237 
238  /* we need to have a real key.. */
239  if (keynum >= NUM_WEPKEYS)
240  return -2;
241  keylen = wlandev->wep_keylens[keynum];
242  if (keylen <= 0)
243  return -3;
244 
245  /* use a random IV. And skip known weak ones. */
246  get_random_bytes(iv, 3);
247  while ((iv[1] == 0xff) && (iv[0] >= 3) && (iv[0] < keylen))
248  get_random_bytes(iv, 3);
249 
250  iv[3] = (keynum & 0x03) << 6;
251 
252  key[0] = iv[0];
253  key[1] = iv[1];
254  key[2] = iv[2];
255 
256  /* copy the rest of the key over from the designated key */
257  memcpy(key + 3, wlandev->wep_keys[keynum], keylen);
258 
259  keylen += 3; /* add in IV bytes */
260 
261 #ifdef WEP_DEBUG
262  printk(KERN_DEBUG "E %d (%d/%d %d) %*ph %*phC\n", len,
263  iv[3], keynum, keylen, 3, key, 5, key + 3);
264 #endif
265 
266  /* set up the RC4 state */
267  for (i = 0; i < 256; i++)
268  s[i] = i;
269  j = 0;
270  for (i = 0; i < 256; i++) {
271  j = (j + s[i] + key[i % keylen]) & 0xff;
272  swap(i, j);
273  }
274 
275  /* Update CRC32 then apply RC4 to the data */
276  crc = ~0;
277  i = j = 0;
278  for (k = 0; k < len; k++) {
279  crc = wep_crc32_table[(crc ^ buf[k]) & 0xff] ^ (crc >> 8);
280  i = (i + 1) & 0xff;
281  j = (j + s[i]) & 0xff;
282  swap(i, j);
283  dst[k] = buf[k] ^ s[(s[i] + s[j]) & 0xff];
284  }
285  crc = ~crc;
286 
287  /* now let's encrypt the crc */
288  icv[0] = crc;
289  icv[1] = crc >> 8;
290  icv[2] = crc >> 16;
291  icv[3] = crc >> 24;
292 
293  for (k = 0; k < 4; k++) {
294  i = (i + 1) & 0xff;
295  j = (j + s[i]) & 0xff;
296  swap(i, j);
297  icv[k] ^= s[(s[i] + s[j]) & 0xff];
298  }
299 
300  return 0;
301 }