Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
0002 /*
0003  *
0004  * WEP encode/decode for P80211.
0005  *
0006  * Copyright (C) 2002 AbsoluteValue Systems, Inc.  All Rights Reserved.
0007  * --------------------------------------------------------------------
0008  *
0009  * linux-wlan
0010  *
0011  *   The contents of this file are subject to the Mozilla Public
0012  *   License Version 1.1 (the "License"); you may not use this file
0013  *   except in compliance with the License. You may obtain a copy of
0014  *   the License at http://www.mozilla.org/MPL/
0015  *
0016  *   Software distributed under the License is distributed on an "AS
0017  *   IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
0018  *   implied. See the License for the specific language governing
0019  *   rights and limitations under the License.
0020  *
0021  *   Alternatively, the contents of this file may be used under the
0022  *   terms of the GNU Public License version 2 (the "GPL"), in which
0023  *   case the provisions of the GPL are applicable instead of the
0024  *   above.  If you wish to allow the use of your version of this file
0025  *   only under the terms of the GPL and not to allow others to use
0026  *   your version of this file under the MPL, indicate your decision
0027  *   by deleting the provisions above and replace them with the notice
0028  *   and other provisions required by the GPL.  If you do not delete
0029  *   the provisions above, a recipient may use your version of this
0030  *   file under either the MPL or the GPL.
0031  *
0032  * --------------------------------------------------------------------
0033  *
0034  * Inquiries regarding the linux-wlan Open Source project can be
0035  * made directly to:
0036  *
0037  * AbsoluteValue Systems Inc.
0038  * info@linux-wlan.com
0039  * http://www.linux-wlan.com
0040  *
0041  * --------------------------------------------------------------------
0042  *
0043  * Portions of the development of this software were funded by
0044  * Intersil Corporation as part of PRISM(R) chipset product development.
0045  *
0046  * --------------------------------------------------------------------
0047  */
0048 
0049 /*================================================================*/
0050 /* System Includes */
0051 
0052 #include <linux/crc32.h>
0053 #include <linux/netdevice.h>
0054 #include <linux/wireless.h>
0055 #include <linux/random.h>
0056 #include <linux/kernel.h>
0057 #include "p80211hdr.h"
0058 #include "p80211types.h"
0059 #include "p80211msg.h"
0060 #include "p80211conv.h"
0061 #include "p80211netdev.h"
0062 
0063 #define WEP_KEY(x)       (((x) & 0xC0) >> 6)
0064 
0065 /* keylen in bytes! */
0066 
0067 int wep_change_key(struct wlandevice *wlandev, int keynum, u8 *key, int keylen)
0068 {
0069     if (keylen < 0)
0070         return -1;
0071     if (keylen >= MAX_KEYLEN)
0072         return -1;
0073     if (!key)
0074         return -1;
0075     if (keynum < 0)
0076         return -1;
0077     if (keynum >= NUM_WEPKEYS)
0078         return -1;
0079 
0080     wlandev->wep_keylens[keynum] = keylen;
0081     memcpy(wlandev->wep_keys[keynum], key, keylen);
0082 
0083     return 0;
0084 }
0085 
0086 /*
0087  * 4-byte IV at start of buffer, 4-byte ICV at end of buffer.
0088  * if successful, buf start is payload begin, length -= 8;
0089  */
0090 int wep_decrypt(struct wlandevice *wlandev, u8 *buf, u32 len, int key_override,
0091         u8 *iv, u8 *icv)
0092 {
0093     u32 i, j, k, crc, keylen;
0094     u8 s[256], key[64], c_crc[4];
0095     u8 keyidx;
0096 
0097     /* Needs to be at least 8 bytes of payload */
0098     if (len <= 0)
0099         return -1;
0100 
0101     /* initialize the first bytes of the key from the IV */
0102     key[0] = iv[0];
0103     key[1] = iv[1];
0104     key[2] = iv[2];
0105     keyidx = WEP_KEY(iv[3]);
0106 
0107     if (key_override >= 0)
0108         keyidx = key_override;
0109 
0110     if (keyidx >= NUM_WEPKEYS)
0111         return -2;
0112 
0113     keylen = wlandev->wep_keylens[keyidx];
0114 
0115     if (keylen == 0)
0116         return -3;
0117 
0118     /* copy the rest of the key over from the designated key */
0119     memcpy(key + 3, wlandev->wep_keys[keyidx], keylen);
0120 
0121     keylen += 3;        /* add in IV bytes */
0122 
0123     /* set up the RC4 state */
0124     for (i = 0; i < 256; i++)
0125         s[i] = i;
0126     j = 0;
0127     for (i = 0; i < 256; i++) {
0128         j = (j + s[i] + key[i % keylen]) & 0xff;
0129         swap(i, j);
0130     }
0131 
0132     /* Apply the RC4 to the data, update the CRC32 */
0133     i = 0;
0134     j = 0;
0135     for (k = 0; k < len; k++) {
0136         i = (i + 1) & 0xff;
0137         j = (j + s[i]) & 0xff;
0138         swap(i, j);
0139         buf[k] ^= s[(s[i] + s[j]) & 0xff];
0140     }
0141     crc = ~crc32_le(~0, buf, len);
0142 
0143     /* now let's check the crc */
0144     c_crc[0] = crc;
0145     c_crc[1] = crc >> 8;
0146     c_crc[2] = crc >> 16;
0147     c_crc[3] = crc >> 24;
0148 
0149     for (k = 0; k < 4; k++) {
0150         i = (i + 1) & 0xff;
0151         j = (j + s[i]) & 0xff;
0152         swap(i, j);
0153         if ((c_crc[k] ^ s[(s[i] + s[j]) & 0xff]) != icv[k])
0154             return -(4 | (k << 4)); /* ICV mismatch */
0155     }
0156 
0157     return 0;
0158 }
0159 
0160 /* encrypts in-place. */
0161 int wep_encrypt(struct wlandevice *wlandev, u8 *buf,
0162         u8 *dst, u32 len, int keynum, u8 *iv, u8 *icv)
0163 {
0164     u32 i, j, k, crc, keylen;
0165     u8 s[256], key[64];
0166 
0167     /* no point in WEPping an empty frame */
0168     if (len <= 0)
0169         return -1;
0170 
0171     /* we need to have a real key.. */
0172     if (keynum >= NUM_WEPKEYS)
0173         return -2;
0174     keylen = wlandev->wep_keylens[keynum];
0175     if (keylen <= 0)
0176         return -3;
0177 
0178     /* use a random IV.  And skip known weak ones. */
0179     get_random_bytes(iv, 3);
0180     while ((iv[1] == 0xff) && (iv[0] >= 3) && (iv[0] < keylen))
0181         get_random_bytes(iv, 3);
0182 
0183     iv[3] = (keynum & 0x03) << 6;
0184 
0185     key[0] = iv[0];
0186     key[1] = iv[1];
0187     key[2] = iv[2];
0188 
0189     /* copy the rest of the key over from the designated key */
0190     memcpy(key + 3, wlandev->wep_keys[keynum], keylen);
0191 
0192     keylen += 3;        /* add in IV bytes */
0193 
0194     /* set up the RC4 state */
0195     for (i = 0; i < 256; i++)
0196         s[i] = i;
0197     j = 0;
0198     for (i = 0; i < 256; i++) {
0199         j = (j + s[i] + key[i % keylen]) & 0xff;
0200         swap(i, j);
0201     }
0202 
0203     /* Update CRC32 then apply RC4 to the data */
0204     i = 0;
0205     j = 0;
0206     for (k = 0; k < len; k++) {
0207         i = (i + 1) & 0xff;
0208         j = (j + s[i]) & 0xff;
0209         swap(i, j);
0210         dst[k] = buf[k] ^ s[(s[i] + s[j]) & 0xff];
0211     }
0212     crc = ~crc32_le(~0, buf, len);
0213 
0214     /* now let's encrypt the crc */
0215     icv[0] = crc;
0216     icv[1] = crc >> 8;
0217     icv[2] = crc >> 16;
0218     icv[3] = crc >> 24;
0219 
0220     for (k = 0; k < 4; k++) {
0221         i = (i + 1) & 0xff;
0222         j = (j + s[i]) & 0xff;
0223         swap(i, j);
0224         icv[k] ^= s[(s[i] + s[j]) & 0xff];
0225     }
0226 
0227     return 0;
0228 }