1 /* 2 * Software WEP encryption implementation 3 * Copyright 2002, Jouni Malinen <jkmaline@cc.hut.fi> 4 * Copyright 2003, Instant802 Networks, Inc. 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. 9 */ 10 11 #include <linux/netdevice.h> 12 #include <linux/types.h> 13 #include <linux/random.h> 14 #include <linux/compiler.h> 15 #include <linux/crc32.h> 16 #include <linux/crypto.h> 17 #include <linux/err.h> 18 #include <linux/mm.h> 19 #include <linux/scatterlist.h> 20 #include <linux/slab.h> 21 #include <asm/unaligned.h> 22 23 #include <net/mac80211.h> 24 #include "ieee80211_i.h" 25 #include "wep.h" 26 27 28 int ieee80211_wep_init(struct ieee80211_local *local) 29 { 30 /* start WEP IV from a random value */ 31 get_random_bytes(&local->wep_iv, WEP_IV_LEN); 32 33 local->wep_tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, 34 CRYPTO_ALG_ASYNC); 35 if (IS_ERR(local->wep_tx_tfm)) { 36 local->wep_rx_tfm = ERR_PTR(-EINVAL); 37 return PTR_ERR(local->wep_tx_tfm); 38 } 39 40 local->wep_rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, 41 CRYPTO_ALG_ASYNC); 42 if (IS_ERR(local->wep_rx_tfm)) { 43 crypto_free_blkcipher(local->wep_tx_tfm); 44 local->wep_tx_tfm = ERR_PTR(-EINVAL); 45 return PTR_ERR(local->wep_rx_tfm); 46 } 47 48 return 0; 49 } 50 51 void ieee80211_wep_free(struct ieee80211_local *local) 52 { 53 if (!IS_ERR(local->wep_tx_tfm)) 54 crypto_free_blkcipher(local->wep_tx_tfm); 55 if (!IS_ERR(local->wep_rx_tfm)) 56 crypto_free_blkcipher(local->wep_rx_tfm); 57 } 58 59 static inline bool ieee80211_wep_weak_iv(u32 iv, int keylen) 60 { 61 /* 62 * Fluhrer, Mantin, and Shamir have reported weaknesses in the 63 * key scheduling algorithm of RC4. At least IVs (KeyByte + 3, 64 * 0xff, N) can be used to speedup attacks, so avoid using them. 65 */ 66 if ((iv & 0xff00) == 0xff00) { 67 u8 B = (iv >> 16) & 0xff; 68 if (B >= 3 && B < 3 + keylen) 69 return true; 70 } 71 return false; 72 } 73 74 75 static void ieee80211_wep_get_iv(struct ieee80211_local *local, 76 int keylen, int keyidx, u8 *iv) 77 { 78 local->wep_iv++; 79 if (ieee80211_wep_weak_iv(local->wep_iv, keylen)) 80 local->wep_iv += 0x0100; 81 82 if (!iv) 83 return; 84 85 *iv++ = (local->wep_iv >> 16) & 0xff; 86 *iv++ = (local->wep_iv >> 8) & 0xff; 87 *iv++ = local->wep_iv & 0xff; 88 *iv++ = keyidx << 6; 89 } 90 91 92 static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local, 93 struct sk_buff *skb, 94 int keylen, int keyidx) 95 { 96 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 97 unsigned int hdrlen; 98 u8 *newhdr; 99 100 hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); 101 102 if (WARN_ON(skb_tailroom(skb) < WEP_ICV_LEN || 103 skb_headroom(skb) < WEP_IV_LEN)) 104 return NULL; 105 106 hdrlen = ieee80211_hdrlen(hdr->frame_control); 107 newhdr = skb_push(skb, WEP_IV_LEN); 108 memmove(newhdr, newhdr + WEP_IV_LEN, hdrlen); 109 ieee80211_wep_get_iv(local, keylen, keyidx, newhdr + hdrlen); 110 return newhdr + hdrlen; 111 } 112 113 114 static void ieee80211_wep_remove_iv(struct ieee80211_local *local, 115 struct sk_buff *skb, 116 struct ieee80211_key *key) 117 { 118 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 119 unsigned int hdrlen; 120 121 hdrlen = ieee80211_hdrlen(hdr->frame_control); 122 memmove(skb->data + WEP_IV_LEN, skb->data, hdrlen); 123 skb_pull(skb, WEP_IV_LEN); 124 } 125 126 127 /* Perform WEP encryption using given key. data buffer must have tailroom 128 * for 4-byte ICV. data_len must not include this ICV. Note: this function 129 * does _not_ add IV. data = RC4(data | CRC32(data)) */ 130 int ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, 131 size_t klen, u8 *data, size_t data_len) 132 { 133 struct blkcipher_desc desc = { .tfm = tfm }; 134 struct scatterlist sg; 135 __le32 icv; 136 137 if (IS_ERR(tfm)) 138 return -1; 139 140 icv = cpu_to_le32(~crc32_le(~0, data, data_len)); 141 put_unaligned(icv, (__le32 *)(data + data_len)); 142 143 crypto_blkcipher_setkey(tfm, rc4key, klen); 144 sg_init_one(&sg, data, data_len + WEP_ICV_LEN); 145 crypto_blkcipher_encrypt(&desc, &sg, &sg, sg.length); 146 147 return 0; 148 } 149 150 151 /* Perform WEP encryption on given skb. 4 bytes of extra space (IV) in the 152 * beginning of the buffer 4 bytes of extra space (ICV) in the end of the 153 * buffer will be added. Both IV and ICV will be transmitted, so the 154 * payload length increases with 8 bytes. 155 * 156 * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data)) 157 */ 158 int ieee80211_wep_encrypt(struct ieee80211_local *local, 159 struct sk_buff *skb, 160 const u8 *key, int keylen, int keyidx) 161 { 162 u8 *iv; 163 size_t len; 164 u8 rc4key[3 + WLAN_KEY_LEN_WEP104]; 165 166 iv = ieee80211_wep_add_iv(local, skb, keylen, keyidx); 167 if (!iv) 168 return -1; 169 170 len = skb->len - (iv + WEP_IV_LEN - skb->data); 171 172 /* Prepend 24-bit IV to RC4 key */ 173 memcpy(rc4key, iv, 3); 174 175 /* Copy rest of the WEP key (the secret part) */ 176 memcpy(rc4key + 3, key, keylen); 177 178 /* Add room for ICV */ 179 skb_put(skb, WEP_ICV_LEN); 180 181 return ieee80211_wep_encrypt_data(local->wep_tx_tfm, rc4key, keylen + 3, 182 iv + WEP_IV_LEN, len); 183 } 184 185 186 /* Perform WEP decryption using given key. data buffer includes encrypted 187 * payload, including 4-byte ICV, but _not_ IV. data_len must not include ICV. 188 * Return 0 on success and -1 on ICV mismatch. */ 189 int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, 190 size_t klen, u8 *data, size_t data_len) 191 { 192 struct blkcipher_desc desc = { .tfm = tfm }; 193 struct scatterlist sg; 194 __le32 crc; 195 196 if (IS_ERR(tfm)) 197 return -1; 198 199 crypto_blkcipher_setkey(tfm, rc4key, klen); 200 sg_init_one(&sg, data, data_len + WEP_ICV_LEN); 201 crypto_blkcipher_decrypt(&desc, &sg, &sg, sg.length); 202 203 crc = cpu_to_le32(~crc32_le(~0, data, data_len)); 204 if (memcmp(&crc, data + data_len, WEP_ICV_LEN) != 0) 205 /* ICV mismatch */ 206 return -1; 207 208 return 0; 209 } 210 211 212 /* Perform WEP decryption on given skb. Buffer includes whole WEP part of 213 * the frame: IV (4 bytes), encrypted payload (including SNAP header), 214 * ICV (4 bytes). skb->len includes both IV and ICV. 215 * 216 * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on 217 * failure. If frame is OK, IV and ICV will be removed, i.e., decrypted payload 218 * is moved to the beginning of the skb and skb length will be reduced. 219 */ 220 static int ieee80211_wep_decrypt(struct ieee80211_local *local, 221 struct sk_buff *skb, 222 struct ieee80211_key *key) 223 { 224 u32 klen; 225 u8 *rc4key; 226 u8 keyidx; 227 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 228 unsigned int hdrlen; 229 size_t len; 230 int ret = 0; 231 232 if (!ieee80211_has_protected(hdr->frame_control)) 233 return -1; 234 235 hdrlen = ieee80211_hdrlen(hdr->frame_control); 236 if (skb->len < hdrlen + WEP_IV_LEN + WEP_ICV_LEN) 237 return -1; 238 239 len = skb->len - hdrlen - WEP_IV_LEN - WEP_ICV_LEN; 240 241 keyidx = skb->data[hdrlen + 3] >> 6; 242 243 if (!key || keyidx != key->conf.keyidx || key->conf.alg != ALG_WEP) 244 return -1; 245 246 klen = 3 + key->conf.keylen; 247 248 rc4key = kmalloc(klen, GFP_ATOMIC); 249 if (!rc4key) 250 return -1; 251 252 /* Prepend 24-bit IV to RC4 key */ 253 memcpy(rc4key, skb->data + hdrlen, 3); 254 255 /* Copy rest of the WEP key (the secret part) */ 256 memcpy(rc4key + 3, key->conf.key, key->conf.keylen); 257 258 if (ieee80211_wep_decrypt_data(local->wep_rx_tfm, rc4key, klen, 259 skb->data + hdrlen + WEP_IV_LEN, 260 len)) 261 ret = -1; 262 263 kfree(rc4key); 264 265 /* Trim ICV */ 266 skb_trim(skb, skb->len - WEP_ICV_LEN); 267 268 /* Remove IV */ 269 memmove(skb->data + WEP_IV_LEN, skb->data, hdrlen); 270 skb_pull(skb, WEP_IV_LEN); 271 272 return ret; 273 } 274 275 276 bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key) 277 { 278 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 279 unsigned int hdrlen; 280 u8 *ivpos; 281 u32 iv; 282 283 if (!ieee80211_has_protected(hdr->frame_control)) 284 return false; 285 286 hdrlen = ieee80211_hdrlen(hdr->frame_control); 287 ivpos = skb->data + hdrlen; 288 iv = (ivpos[0] << 16) | (ivpos[1] << 8) | ivpos[2]; 289 290 return ieee80211_wep_weak_iv(iv, key->conf.keylen); 291 } 292 293 ieee80211_rx_result 294 ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx) 295 { 296 struct sk_buff *skb = rx->skb; 297 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); 298 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 299 300 if (!ieee80211_is_data(hdr->frame_control) && 301 !ieee80211_is_auth(hdr->frame_control)) 302 return RX_CONTINUE; 303 304 if (!(status->flag & RX_FLAG_DECRYPTED)) { 305 if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) 306 return RX_DROP_UNUSABLE; 307 } else if (!(status->flag & RX_FLAG_IV_STRIPPED)) { 308 ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key); 309 /* remove ICV */ 310 skb_trim(rx->skb, rx->skb->len - WEP_ICV_LEN); 311 } 312 313 return RX_CONTINUE; 314 } 315 316 static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) 317 { 318 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 319 320 if (!info->control.hw_key) { 321 if (ieee80211_wep_encrypt(tx->local, skb, tx->key->conf.key, 322 tx->key->conf.keylen, 323 tx->key->conf.keyidx)) 324 return -1; 325 } else if (info->control.hw_key->flags & 326 IEEE80211_KEY_FLAG_GENERATE_IV) { 327 if (!ieee80211_wep_add_iv(tx->local, skb, 328 tx->key->conf.keylen, 329 tx->key->conf.keyidx)) 330 return -1; 331 } 332 333 return 0; 334 } 335 336 ieee80211_tx_result 337 ieee80211_crypto_wep_encrypt(struct ieee80211_tx_data *tx) 338 { 339 struct sk_buff *skb; 340 341 ieee80211_tx_set_protected(tx); 342 343 skb = tx->skb; 344 do { 345 if (wep_encrypt_skb(tx, skb) < 0) { 346 I802_DEBUG_INC(tx->local->tx_handlers_drop_wep); 347 return TX_DROP; 348 } 349 } while ((skb = skb->next)); 350 351 return TX_CONTINUE; 352 } 353