00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <linux/config.h>
00013 #include <linux/version.h>
00014 #include <linux/module.h>
00015 #include <linux/init.h>
00016 #include <linux/slab.h>
00017 #include <linux/random.h>
00018 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44))
00019 #include <linux/tqueue.h>
00020 #else
00021 #include <linux/workqueue.h>
00022 #endif
00023 #include <asm/string.h>
00024
00025 #include "hostap_crypt.h"
00026 #include "hostap_compat.h"
00027
00028 MODULE_AUTHOR("Jouni Malinen");
00029 MODULE_DESCRIPTION("Host AP crypt: WEP");
00030 MODULE_LICENSE("GPL");
00031
00032
00033 struct prism2_wep_data {
00034 u32 iv;
00035 #define WEP_KEYS 4
00036 #define WEP_KEY_LEN 13
00037 u8 keys[WEP_KEYS][WEP_KEY_LEN + 1];
00038 u8 key_lens[WEP_KEYS];
00039 int tx_key;
00040 };
00041
00042 static const __u32 crc32_table[256] = {
00043 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
00044 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
00045 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
00046 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
00047 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
00048 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
00049 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
00050 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
00051 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
00052 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
00053 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
00054 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
00055 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
00056 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
00057 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
00058 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
00059 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
00060 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
00061 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
00062 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
00063 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
00064 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
00065 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
00066 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
00067 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
00068 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
00069 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
00070 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
00071 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
00072 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
00073 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
00074 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
00075 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
00076 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
00077 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
00078 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
00079 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
00080 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
00081 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
00082 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
00083 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
00084 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
00085 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
00086 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
00087 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
00088 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
00089 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
00090 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
00091 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
00092 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
00093 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
00094 0x2d02ef8dL
00095 };
00096
00097
00098 static void * prism2_wep_init(void)
00099 {
00100 struct prism2_wep_data *priv;
00101
00102 #ifdef NEW_MODULE_CODE
00103 if (!try_module_get(THIS_MODULE))
00104 return NULL;
00105 #else
00106 MOD_INC_USE_COUNT;
00107 #endif
00108
00109 priv = (struct prism2_wep_data *) kmalloc(sizeof(*priv), GFP_ATOMIC);
00110 if (priv == NULL) {
00111 #ifdef NEW_MODULE_CODE
00112 module_put(THIS_MODULE);
00113 #else
00114 MOD_DEC_USE_COUNT;
00115 #endif
00116 return NULL;
00117 }
00118 memset(priv, 0, sizeof(*priv));
00119
00120
00121 get_random_bytes(&priv->iv, 4);
00122
00123 return priv;
00124 }
00125
00126
00127 static void prism2_wep_deinit(void *priv)
00128 {
00129 kfree(priv);
00130 #ifdef NEW_MODULE_CODE
00131 module_put(THIS_MODULE);
00132 #else
00133 MOD_DEC_USE_COUNT;
00134 #endif
00135 }
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 static int prism2_wep_encrypt(u8 *buf, int len, void *priv)
00146 {
00147 struct prism2_wep_data *wep = priv;
00148 u32 i, j, k, crc, klen;
00149 u8 S[256], key[WEP_KEY_LEN + 3];
00150 u8 kpos, *pos;
00151 #define S_SWAP(a,b) do { u8 t = S[a]; S[a] = S[b]; S[b] = t; } while(0)
00152
00153 klen = 3 + wep->key_lens[wep->tx_key];
00154
00155 wep->iv++;
00156
00157
00158
00159
00160 if ((wep->iv & 0xff00) == 0xff00) {
00161 u8 B = (wep->iv >> 16) & 0xff;
00162 if (B >= 3 && B < klen)
00163 wep->iv += 0x0100;
00164 }
00165
00166
00167 pos = buf;
00168 *pos++ = key[0] = (wep->iv >> 16) & 0xff;
00169 *pos++ = key[1] = (wep->iv >> 8) & 0xff;
00170 *pos++ = key[2] = wep->iv & 0xff;
00171 *pos++ = wep->tx_key << 6;
00172
00173
00174 memcpy(key + 3, wep->keys[wep->tx_key],
00175 wep->key_lens[wep->tx_key]);
00176
00177
00178 for (i = 0; i < 256; i++)
00179 S[i] = i;
00180 j = 0;
00181 kpos = 0;
00182 for (i = 0; i < 256; i++) {
00183 j = (j + S[i] + key[kpos]) & 0xff;
00184 kpos++;
00185 if (kpos >= klen)
00186 kpos = 0;
00187 S_SWAP(i, j);
00188 }
00189
00190
00191 crc = ~0;
00192 i = j = 0;
00193 for (k = 0; k < len; k++) {
00194 crc = crc32_table[(crc ^ *pos) & 0xff] ^ (crc >> 8);
00195 i = (i + 1) & 0xff;
00196 j = (j + S[i]) & 0xff;
00197 S_SWAP(i, j);
00198 *pos++ ^= S[(S[i] + S[j]) & 0xff];
00199 }
00200 crc = ~crc;
00201
00202
00203 pos[0] = crc;
00204 pos[1] = crc >> 8;
00205 pos[2] = crc >> 16;
00206 pos[3] = crc >> 24;
00207 for (k = 0; k < 4; k++) {
00208 i = (i + 1) & 0xff;
00209 j = (j + S[i]) & 0xff;
00210 S_SWAP(i, j);
00211 *pos++ ^= S[(S[i] + S[j]) & 0xff];
00212 }
00213
00214 return len + 8;
00215 }
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226 static int prism2_wep_decrypt(u8 *buf, int len, void *priv)
00227 {
00228 struct prism2_wep_data *wep = priv;
00229 u32 i, j, k, crc, klen;
00230 u8 S[256], key[WEP_KEY_LEN + 3];
00231 u8 keyidx, kpos, *dpos, *cpos;
00232
00233 if (len < 8)
00234 return -1;
00235
00236 key[0] = buf[0];
00237 key[1] = buf[1];
00238 key[2] = buf[2];
00239 keyidx = buf[3] >> 6;
00240
00241 klen = 3 + wep->key_lens[keyidx];
00242
00243
00244 memcpy(key + 3, wep->keys[keyidx], wep->key_lens[keyidx]);
00245
00246
00247 for (i = 0; i < 256; i++)
00248 S[i] = i;
00249 j = 0;
00250 kpos = 0;
00251 for (i = 0; i < 256; i++) {
00252 j = (j + S[i] + key[kpos]) & 0xff;
00253 kpos++;
00254 if (kpos >= klen)
00255 kpos = 0;
00256 S_SWAP(i, j);
00257 }
00258
00259
00260 dpos = buf;
00261 cpos = buf + 4;
00262 crc = ~0;
00263 i = j = 0;
00264 for (k = 0; k < len - 8; k++) {
00265 i = (i + 1) & 0xff;
00266 j = (j + S[i]) & 0xff;
00267 S_SWAP(i, j);
00268 *dpos = *cpos++ ^ S[(S[i] + S[j]) & 0xff];
00269 crc = crc32_table[(crc ^ *dpos++) & 0xff] ^ (crc >> 8);
00270 }
00271 crc = ~crc;
00272
00273
00274
00275 dpos[0] = crc;
00276 dpos[1] = crc >> 8;
00277 dpos[2] = crc >> 16;
00278 dpos[3] = crc >> 24;
00279 for (k = 0; k < 4; k++) {
00280 i = (i + 1) & 0xff;
00281 j = (j + S[i]) & 0xff;
00282 S_SWAP(i, j);
00283 if ((*dpos++ ^ S[(S[i] + S[j]) & 0xff]) != *cpos++) {
00284
00285 return -1;
00286 }
00287 }
00288
00289 return len - 8;
00290 }
00291
00292
00293 static int prism2_wep_set_key(int idx, void *key, int len, void *priv)
00294 {
00295 struct prism2_wep_data *wep = priv;
00296
00297 if (idx < 0 || idx >= WEP_KEYS || len < 0 || len > WEP_KEY_LEN)
00298 return -1;
00299
00300 memcpy(wep->keys[idx], key, len);
00301 wep->key_lens[idx] = len;
00302
00303 return 0;
00304 }
00305
00306
00307 static int prism2_wep_get_key(int idx, void *key, int len, void *priv)
00308 {
00309 struct prism2_wep_data *wep = priv;
00310
00311 if (idx < 0 || idx >= WEP_KEYS || len < wep->key_lens[idx])
00312 return -1;
00313
00314 memcpy(key, wep->keys[idx], wep->key_lens[idx]);
00315
00316 return wep->key_lens[idx];
00317 }
00318
00319
00320 static int prism2_wep_set_key_idx(int idx, void *priv)
00321 {
00322 struct prism2_wep_data *wep = priv;
00323
00324 if (idx < 0 || idx >= WEP_KEYS || wep->key_lens[idx] == 0)
00325 return -1;
00326
00327 wep->tx_key = idx;
00328
00329 return 0;
00330 }
00331
00332
00333 static int prism2_wep_get_key_idx(void *priv)
00334 {
00335 struct prism2_wep_data *wep = priv;
00336 return wep->tx_key;
00337 }
00338
00339
00340 static struct hostap_crypto_ops hostap_crypt_wep = {
00341 .name = "WEP",
00342 .init = prism2_wep_init,
00343 .deinit = prism2_wep_deinit,
00344 .encrypt = prism2_wep_encrypt,
00345 .decrypt = prism2_wep_decrypt,
00346 .set_key = prism2_wep_set_key,
00347 .get_key = prism2_wep_get_key,
00348 .set_key_idx = prism2_wep_set_key_idx,
00349 .get_key_idx = prism2_wep_get_key_idx,
00350 .extra_prefix_len = 4 ,
00351 .extra_postfix_len = 4
00352 };
00353
00354
00355 static int __init hostap_crypto_wep_init(void)
00356 {
00357 if (hostap_register_crypto_ops(&hostap_crypt_wep) < 0)
00358 return -1;
00359
00360 return 0;
00361 }
00362
00363
00364 static void __exit hostap_crypto_wep_exit(void)
00365 {
00366 hostap_unregister_crypto_ops(&hostap_crypt_wep);
00367 }
00368
00369
00370 module_init(hostap_crypto_wep_init);
00371 module_exit(hostap_crypto_wep_exit);