1 /* 2 * Host AP crypt: host-based WEP encryption implementation for Host AP driver 3 * 4 * Copyright (c) 2002-2004, Jouni Malinen <jkmaline@cc.hut.fi> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. See README and COPYING for 9 * more details. 10 */ 11 12 #include <linux/module.h> 13 #include <linux/init.h> 14 #include <linux/slab.h> 15 #include <linux/random.h> 16 #include <linux/skbuff.h> 17 #include <linux/string.h> 18 19 #include "ieee80211.h" 20 21 #include <crypto/skcipher.h> 22 #include <linux/scatterlist.h> 23 #include <linux/crc32.h> 24 25 MODULE_AUTHOR("Jouni Malinen"); 26 MODULE_DESCRIPTION("Host AP crypt: WEP"); 27 MODULE_LICENSE("GPL"); 28 29 struct prism2_wep_data { 30 u32 iv; 31 #define WEP_KEY_LEN 13 32 u8 key[WEP_KEY_LEN + 1]; 33 u8 key_len; 34 u8 key_idx; 35 struct crypto_skcipher *tx_tfm; 36 struct crypto_skcipher *rx_tfm; 37 }; 38 39 40 static void *prism2_wep_init(int keyidx) 41 { 42 struct prism2_wep_data *priv; 43 44 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 45 if (!priv) 46 return NULL; 47 priv->key_idx = keyidx; 48 49 priv->tx_tfm = crypto_alloc_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); 50 if (IS_ERR(priv->tx_tfm)) 51 goto free_priv; 52 priv->rx_tfm = crypto_alloc_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); 53 if (IS_ERR(priv->rx_tfm)) 54 goto free_tx; 55 56 /* start WEP IV from a random value */ 57 get_random_bytes(&priv->iv, 4); 58 59 return priv; 60 free_tx: 61 crypto_free_skcipher(priv->tx_tfm); 62 free_priv: 63 kfree(priv); 64 return NULL; 65 } 66 67 68 static void prism2_wep_deinit(void *priv) 69 { 70 struct prism2_wep_data *_priv = priv; 71 72 if (_priv) { 73 crypto_free_skcipher(_priv->tx_tfm); 74 crypto_free_skcipher(_priv->rx_tfm); 75 } 76 kfree(priv); 77 } 78 79 /* Perform WEP encryption on given skb that has at least 4 bytes of headroom 80 * for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted, 81 * so the payload length increases with 8 bytes. 82 * 83 * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data)) 84 */ 85 static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) 86 { 87 struct prism2_wep_data *wep = priv; 88 u32 klen, len; 89 u8 key[WEP_KEY_LEN + 3]; 90 u8 *pos; 91 struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); 92 u32 crc; 93 u8 *icv; 94 struct scatterlist sg; 95 int err; 96 97 if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 || 98 skb->len < hdr_len) 99 return -1; 100 101 len = skb->len - hdr_len; 102 pos = skb_push(skb, 4); 103 memmove(pos, pos + 4, hdr_len); 104 pos += hdr_len; 105 106 klen = 3 + wep->key_len; 107 108 wep->iv++; 109 110 /* Fluhrer, Mantin, and Shamir have reported weaknesses in the key 111 * scheduling algorithm of RC4. At least IVs (KeyByte + 3, 0xff, N) 112 * can be used to speedup attacks, so avoid using them. 113 */ 114 if ((wep->iv & 0xff00) == 0xff00) { 115 u8 B = (wep->iv >> 16) & 0xff; 116 117 if (B >= 3 && B < klen) 118 wep->iv += 0x0100; 119 } 120 121 /* Prepend 24-bit IV to RC4 key and TX frame */ 122 *pos++ = key[0] = (wep->iv >> 16) & 0xff; 123 *pos++ = key[1] = (wep->iv >> 8) & 0xff; 124 *pos++ = key[2] = wep->iv & 0xff; 125 *pos++ = wep->key_idx << 6; 126 127 /* Copy rest of the WEP key (the secret part) */ 128 memcpy(key + 3, wep->key, wep->key_len); 129 130 if (!tcb_desc->bHwSec) { 131 SKCIPHER_REQUEST_ON_STACK(req, wep->tx_tfm); 132 133 /* Append little-endian CRC32 and encrypt it to produce ICV */ 134 crc = ~crc32_le(~0, pos, len); 135 icv = skb_put(skb, 4); 136 icv[0] = crc; 137 icv[1] = crc >> 8; 138 icv[2] = crc >> 16; 139 icv[3] = crc >> 24; 140 141 crypto_skcipher_setkey(wep->tx_tfm, key, klen); 142 sg_init_one(&sg, pos, len+4); 143 144 skcipher_request_set_tfm(req, wep->tx_tfm); 145 skcipher_request_set_callback(req, 0, NULL, NULL); 146 skcipher_request_set_crypt(req, &sg, &sg, len + 4, NULL); 147 148 err = crypto_skcipher_encrypt(req); 149 skcipher_request_zero(req); 150 return err; 151 } 152 153 return 0; 154 } 155 156 157 /* Perform WEP decryption on given buffer. Buffer includes whole WEP part of 158 * the frame: IV (4 bytes), encrypted payload (including SNAP header), 159 * ICV (4 bytes). len includes both IV and ICV. 160 * 161 * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on 162 * failure. If frame is OK, IV and ICV will be removed. 163 */ 164 static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) 165 { 166 struct prism2_wep_data *wep = priv; 167 u32 klen, plen; 168 u8 key[WEP_KEY_LEN + 3]; 169 u8 keyidx, *pos; 170 struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); 171 u32 crc; 172 u8 icv[4]; 173 struct scatterlist sg; 174 int err; 175 176 if (skb->len < hdr_len + 8) 177 return -1; 178 179 pos = skb->data + hdr_len; 180 key[0] = *pos++; 181 key[1] = *pos++; 182 key[2] = *pos++; 183 keyidx = *pos++ >> 6; 184 if (keyidx != wep->key_idx) 185 return -1; 186 187 klen = 3 + wep->key_len; 188 189 /* Copy rest of the WEP key (the secret part) */ 190 memcpy(key + 3, wep->key, wep->key_len); 191 192 /* Apply RC4 to data and compute CRC32 over decrypted data */ 193 plen = skb->len - hdr_len - 8; 194 195 if (!tcb_desc->bHwSec) { 196 SKCIPHER_REQUEST_ON_STACK(req, wep->rx_tfm); 197 198 crypto_skcipher_setkey(wep->rx_tfm, key, klen); 199 sg_init_one(&sg, pos, plen+4); 200 201 skcipher_request_set_tfm(req, wep->rx_tfm); 202 skcipher_request_set_callback(req, 0, NULL, NULL); 203 skcipher_request_set_crypt(req, &sg, &sg, plen + 4, NULL); 204 205 err = crypto_skcipher_decrypt(req); 206 skcipher_request_zero(req); 207 if (err) 208 return -7; 209 210 crc = ~crc32_le(~0, pos, plen); 211 icv[0] = crc; 212 icv[1] = crc >> 8; 213 icv[2] = crc >> 16; 214 icv[3] = crc >> 24; 215 if (memcmp(icv, pos + plen, 4) != 0) { 216 /* ICV mismatch - drop frame */ 217 return -2; 218 } 219 } 220 /* Remove IV and ICV */ 221 memmove(skb->data + 4, skb->data, hdr_len); 222 skb_pull(skb, 4); 223 skb_trim(skb, skb->len - 4); 224 225 return 0; 226 } 227 228 229 static int prism2_wep_set_key(void *key, int len, u8 *seq, void *priv) 230 { 231 struct prism2_wep_data *wep = priv; 232 233 if (len < 0 || len > WEP_KEY_LEN) 234 return -1; 235 236 memcpy(wep->key, key, len); 237 wep->key_len = len; 238 239 return 0; 240 } 241 242 243 static int prism2_wep_get_key(void *key, int len, u8 *seq, void *priv) 244 { 245 struct prism2_wep_data *wep = priv; 246 247 if (len < wep->key_len) 248 return -1; 249 250 memcpy(key, wep->key, wep->key_len); 251 252 return wep->key_len; 253 } 254 255 256 static char *prism2_wep_print_stats(char *p, void *priv) 257 { 258 struct prism2_wep_data *wep = priv; 259 260 p += sprintf(p, "key[%d] alg=WEP len=%d\n", 261 wep->key_idx, wep->key_len); 262 return p; 263 } 264 265 266 static struct ieee80211_crypto_ops ieee80211_crypt_wep = { 267 .name = "WEP", 268 .init = prism2_wep_init, 269 .deinit = prism2_wep_deinit, 270 .encrypt_mpdu = prism2_wep_encrypt, 271 .decrypt_mpdu = prism2_wep_decrypt, 272 .encrypt_msdu = NULL, 273 .decrypt_msdu = NULL, 274 .set_key = prism2_wep_set_key, 275 .get_key = prism2_wep_get_key, 276 .print_stats = prism2_wep_print_stats, 277 .extra_prefix_len = 4, /* IV */ 278 .extra_postfix_len = 4, /* ICV */ 279 .owner = THIS_MODULE, 280 }; 281 282 int __init ieee80211_crypto_wep_init(void) 283 { 284 return ieee80211_register_crypto_ops(&ieee80211_crypt_wep); 285 } 286 287 void __exit ieee80211_crypto_wep_exit(void) 288 { 289 ieee80211_unregister_crypto_ops(&ieee80211_crypt_wep); 290 } 291 292