1 // SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
4 * WEP encode/decode for P80211.
6 * Copyright (C) 2002 AbsoluteValue Systems, Inc. All Rights Reserved.
7 * --------------------------------------------------------------------
11 * --------------------------------------------------------------------
13 * Inquiries regarding the linux-wlan Open Source project can be
16 * AbsoluteValue Systems Inc.
18 * http://www.linux-wlan.com
20 * --------------------------------------------------------------------
22 * Portions of the development of this software were funded by
23 * Intersil Corporation as part of PRISM(R) chipset product development.
25 * --------------------------------------------------------------------
28 /*================================================================*/
31 #include <linux/crc32.h>
32 #include <linux/netdevice.h>
33 #include <linux/wireless.h>
34 #include <linux/random.h>
35 #include <linux/kernel.h>
36 #include "p80211hdr.h"
37 #include "p80211types.h"
38 #include "p80211msg.h"
39 #include "p80211conv.h"
40 #include "p80211netdev.h"
42 #define WEP_KEY(x) (((x) & 0xC0) >> 6)
44 /* keylen in bytes! */
46 int wep_change_key(struct wlandevice *wlandev, int keynum, u8 *key, int keylen)
50 if (keylen >= MAX_KEYLEN)
56 if (keynum >= NUM_WEPKEYS)
59 wlandev->wep_keylens[keynum] = keylen;
60 memcpy(wlandev->wep_keys[keynum], key, keylen);
66 * 4-byte IV at start of buffer, 4-byte ICV at end of buffer.
67 * if successful, buf start is payload begin, length -= 8;
69 int wep_decrypt(struct wlandevice *wlandev, u8 *buf, u32 len, int key_override,
72 u32 i, j, k, crc, keylen;
73 u8 s[256], key[64], c_crc[4];
76 /* Needs to be at least 8 bytes of payload */
80 /* initialize the first bytes of the key from the IV */
84 keyidx = WEP_KEY(iv[3]);
86 if (key_override >= 0)
87 keyidx = key_override;
89 if (keyidx >= NUM_WEPKEYS)
92 keylen = wlandev->wep_keylens[keyidx];
97 /* copy the rest of the key over from the designated key */
98 memcpy(key + 3, wlandev->wep_keys[keyidx], keylen);
100 keylen += 3; /* add in IV bytes */
102 /* set up the RC4 state */
103 for (i = 0; i < 256; i++)
106 for (i = 0; i < 256; i++) {
107 j = (j + s[i] + key[i % keylen]) & 0xff;
111 /* Apply the RC4 to the data, update the CRC32 */
114 for (k = 0; k < len; k++) {
116 j = (j + s[i]) & 0xff;
118 buf[k] ^= s[(s[i] + s[j]) & 0xff];
120 crc = ~crc32_le(~0, buf, len);
122 /* now let's check the crc */
125 c_crc[2] = crc >> 16;
126 c_crc[3] = crc >> 24;
128 for (k = 0; k < 4; k++) {
130 j = (j + s[i]) & 0xff;
132 if ((c_crc[k] ^ s[(s[i] + s[j]) & 0xff]) != icv[k])
133 return -(4 | (k << 4)); /* ICV mismatch */
139 /* encrypts in-place. */
140 int wep_encrypt(struct wlandevice *wlandev, u8 *buf,
141 u8 *dst, u32 len, int keynum, u8 *iv, u8 *icv)
143 u32 i, j, k, crc, keylen;
146 /* no point in WEPping an empty frame */
150 /* we need to have a real key.. */
151 if (keynum >= NUM_WEPKEYS)
153 keylen = wlandev->wep_keylens[keynum];
157 /* use a random IV. And skip known weak ones. */
158 get_random_bytes(iv, 3);
159 while ((iv[1] == 0xff) && (iv[0] >= 3) && (iv[0] < keylen))
160 get_random_bytes(iv, 3);
162 iv[3] = (keynum & 0x03) << 6;
168 /* copy the rest of the key over from the designated key */
169 memcpy(key + 3, wlandev->wep_keys[keynum], keylen);
171 keylen += 3; /* add in IV bytes */
173 /* set up the RC4 state */
174 for (i = 0; i < 256; i++)
177 for (i = 0; i < 256; i++) {
178 j = (j + s[i] + key[i % keylen]) & 0xff;
182 /* Update CRC32 then apply RC4 to the data */
185 for (k = 0; k < len; k++) {
187 j = (j + s[i]) & 0xff;
189 dst[k] = buf[k] ^ s[(s[i] + s[j]) & 0xff];
191 crc = ~crc32_le(~0, buf, len);
193 /* now let's encrypt the crc */
199 for (k = 0; k < 4; k++) {
201 j = (j + s[i]) & 0xff;
203 icv[k] ^= s[(s[i] + s[j]) & 0xff];