root/drivers/staging/wlan-ng/p80211wep.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wep_change_key
  2. wep_decrypt
  3. wep_encrypt

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

/* [<][>][^][v][top][bottom][index][help] */