00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <linux/netdevice.h>
00012 #include <linux/types.h>
00013 #include <linux/random.h>
00014 #include <linux/compiler.h>
00015 #include <linux/crc32.h>
00016 #include <linux/crypto.h>
00017 #include <linux/err.h>
00018 #include <linux/mm.h>
00019 #include <linux/scatterlist.h>
00020 #include <linux/slab.h>
00021 #include <asm/unaligned.h>
00022
00023 #include <net/mac80211.h>
00024 #include "ieee80211_i.h"
00025 #include "wep.h"
00026
00027
00028 int ieee80211_wep_init(struct ieee80211_local *local)
00029 {
00030
00031 get_random_bytes(&local->wep_iv, WEP_IV_LEN);
00032
00033 local->wep_tx_tfm = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC);
00034 if (IS_ERR(local->wep_tx_tfm)) {
00035 local->wep_rx_tfm = ERR_PTR(-EINVAL);
00036 return PTR_ERR(local->wep_tx_tfm);
00037 }
00038
00039 local->wep_rx_tfm = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC);
00040 if (IS_ERR(local->wep_rx_tfm)) {
00041 crypto_free_cipher(local->wep_tx_tfm);
00042 local->wep_tx_tfm = ERR_PTR(-EINVAL);
00043 return PTR_ERR(local->wep_rx_tfm);
00044 }
00045
00046 return 0;
00047 }
00048
00049 void ieee80211_wep_free(struct ieee80211_local *local)
00050 {
00051 if (!IS_ERR(local->wep_tx_tfm))
00052 crypto_free_cipher(local->wep_tx_tfm);
00053 if (!IS_ERR(local->wep_rx_tfm))
00054 crypto_free_cipher(local->wep_rx_tfm);
00055 }
00056
00057 static inline bool ieee80211_wep_weak_iv(u32 iv, int keylen)
00058 {
00059
00060
00061
00062
00063
00064 if ((iv & 0xff00) == 0xff00) {
00065 u8 B = (iv >> 16) & 0xff;
00066 if (B >= 3 && B < 3 + keylen)
00067 return true;
00068 }
00069 return false;
00070 }
00071
00072
00073 static void ieee80211_wep_get_iv(struct ieee80211_local *local,
00074 int keylen, int keyidx, u8 *iv)
00075 {
00076 local->wep_iv++;
00077 if (ieee80211_wep_weak_iv(local->wep_iv, keylen))
00078 local->wep_iv += 0x0100;
00079
00080 if (!iv)
00081 return;
00082
00083 *iv++ = (local->wep_iv >> 16) & 0xff;
00084 *iv++ = (local->wep_iv >> 8) & 0xff;
00085 *iv++ = local->wep_iv & 0xff;
00086 *iv++ = keyidx << 6;
00087 }
00088
00089
00090 static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local,
00091 struct sk_buff *skb,
00092 int keylen, int keyidx)
00093 {
00094 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
00095 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
00096 unsigned int hdrlen;
00097 u8 *newhdr;
00098
00099 hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
00100
00101 if (WARN_ON(skb_tailroom(skb) < WEP_ICV_LEN ||
00102 skb_headroom(skb) < WEP_IV_LEN))
00103 return NULL;
00104
00105 hdrlen = ieee80211_hdrlen(hdr->frame_control);
00106 newhdr = skb_push(skb, WEP_IV_LEN);
00107 memmove(newhdr, newhdr + WEP_IV_LEN, hdrlen);
00108
00109
00110 if (info->control.hw_key &&
00111 (info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))
00112 return newhdr + hdrlen;
00113
00114 skb_set_network_header(skb, skb_network_offset(skb) + WEP_IV_LEN);
00115 ieee80211_wep_get_iv(local, keylen, keyidx, newhdr + hdrlen);
00116 return newhdr + hdrlen;
00117 }
00118
00119
00120 static void ieee80211_wep_remove_iv(struct ieee80211_local *local,
00121 struct sk_buff *skb,
00122 struct ieee80211_key *key)
00123 {
00124 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
00125 unsigned int hdrlen;
00126
00127 hdrlen = ieee80211_hdrlen(hdr->frame_control);
00128 memmove(skb->data + WEP_IV_LEN, skb->data, hdrlen);
00129 skb_pull(skb, WEP_IV_LEN);
00130 }
00131
00132
00133
00134
00135
00136 int ieee80211_wep_encrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
00137 size_t klen, u8 *data, size_t data_len)
00138 {
00139 __le32 icv;
00140 int i;
00141
00142 if (IS_ERR(tfm))
00143 return -1;
00144
00145 icv = cpu_to_le32(~crc32_le(~0, data, data_len));
00146 put_unaligned(icv, (__le32 *)(data + data_len));
00147
00148 crypto_cipher_setkey(tfm, rc4key, klen);
00149 for (i = 0; i < data_len + WEP_ICV_LEN; i++)
00150 crypto_cipher_encrypt_one(tfm, data + i, data + i);
00151
00152 return 0;
00153 }
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 int ieee80211_wep_encrypt(struct ieee80211_local *local,
00164 struct sk_buff *skb,
00165 const u8 *key, int keylen, int keyidx)
00166 {
00167 u8 *iv;
00168 size_t len;
00169 u8 rc4key[3 + WLAN_KEY_LEN_WEP104];
00170
00171 iv = ieee80211_wep_add_iv(local, skb, keylen, keyidx);
00172 if (!iv)
00173 return -1;
00174
00175 len = skb->len - (iv + WEP_IV_LEN - skb->data);
00176
00177
00178 memcpy(rc4key, iv, 3);
00179
00180
00181 memcpy(rc4key + 3, key, keylen);
00182
00183
00184 skb_put(skb, WEP_ICV_LEN);
00185
00186 return ieee80211_wep_encrypt_data(local->wep_tx_tfm, rc4key, keylen + 3,
00187 iv + WEP_IV_LEN, len);
00188 }
00189
00190
00191
00192
00193
00194 int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
00195 size_t klen, u8 *data, size_t data_len)
00196 {
00197 __le32 crc;
00198 int i;
00199
00200 if (IS_ERR(tfm))
00201 return -1;
00202
00203 crypto_cipher_setkey(tfm, rc4key, klen);
00204 for (i = 0; i < data_len + WEP_ICV_LEN; i++)
00205 crypto_cipher_decrypt_one(tfm, data + i, data + i);
00206
00207 crc = cpu_to_le32(~crc32_le(~0, data, data_len));
00208 if (memcmp(&crc, data + data_len, WEP_ICV_LEN) != 0)
00209
00210 return -1;
00211
00212 return 0;
00213 }
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 static int ieee80211_wep_decrypt(struct ieee80211_local *local,
00225 struct sk_buff *skb,
00226 struct ieee80211_key *key)
00227 {
00228 u32 klen;
00229 u8 rc4key[3 + WLAN_KEY_LEN_WEP104];
00230 u8 keyidx;
00231 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
00232 unsigned int hdrlen;
00233 size_t len;
00234 int ret = 0;
00235
00236 if (!ieee80211_has_protected(hdr->frame_control))
00237 return -1;
00238
00239 hdrlen = ieee80211_hdrlen(hdr->frame_control);
00240 if (skb->len < hdrlen + WEP_IV_LEN + WEP_ICV_LEN)
00241 return -1;
00242
00243 len = skb->len - hdrlen - WEP_IV_LEN - WEP_ICV_LEN;
00244
00245 keyidx = skb->data[hdrlen + 3] >> 6;
00246
00247 if (!key || keyidx != key->conf.keyidx)
00248 return -1;
00249
00250 klen = 3 + key->conf.keylen;
00251
00252
00253 memcpy(rc4key, skb->data + hdrlen, 3);
00254
00255
00256 memcpy(rc4key + 3, key->conf.key, key->conf.keylen);
00257
00258 if (ieee80211_wep_decrypt_data(local->wep_rx_tfm, rc4key, klen,
00259 skb->data + hdrlen + WEP_IV_LEN,
00260 len))
00261 ret = -1;
00262
00263
00264 skb_trim(skb, skb->len - WEP_ICV_LEN);
00265
00266
00267 memmove(skb->data + WEP_IV_LEN, skb->data, hdrlen);
00268 skb_pull(skb, WEP_IV_LEN);
00269
00270 return ret;
00271 }
00272
00273
00274 static bool ieee80211_wep_is_weak_iv(struct sk_buff *skb,
00275 struct ieee80211_key *key)
00276 {
00277 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
00278 unsigned int hdrlen;
00279 u8 *ivpos;
00280 u32 iv;
00281
00282 hdrlen = ieee80211_hdrlen(hdr->frame_control);
00283 ivpos = skb->data + hdrlen;
00284 iv = (ivpos[0] << 16) | (ivpos[1] << 8) | ivpos[2];
00285
00286 return ieee80211_wep_weak_iv(iv, key->conf.keylen);
00287 }
00288
00289 ieee80211_rx_result
00290 ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx)
00291 {
00292 struct sk_buff *skb = rx->skb;
00293 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
00294 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
00295 __le16 fc = hdr->frame_control;
00296
00297 if (!ieee80211_is_data(fc) && !ieee80211_is_auth(fc))
00298 return RX_CONTINUE;
00299
00300 if (!(status->flag & RX_FLAG_DECRYPTED)) {
00301 if (skb_linearize(rx->skb))
00302 return RX_DROP_UNUSABLE;
00303 if (rx->sta && ieee80211_wep_is_weak_iv(rx->skb, rx->key))
00304 rx->sta->wep_weak_iv_count++;
00305 if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key))
00306 return RX_DROP_UNUSABLE;
00307 } else if (!(status->flag & RX_FLAG_IV_STRIPPED)) {
00308 if (!pskb_may_pull(rx->skb, ieee80211_hdrlen(fc) + WEP_IV_LEN))
00309 return RX_DROP_UNUSABLE;
00310 if (rx->sta && ieee80211_wep_is_weak_iv(rx->skb, rx->key))
00311 rx->sta->wep_weak_iv_count++;
00312 ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key);
00313
00314 if (pskb_trim(rx->skb, rx->skb->len - WEP_ICV_LEN))
00315 return RX_DROP_UNUSABLE;
00316 }
00317
00318 return RX_CONTINUE;
00319 }
00320
00321 static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
00322 {
00323 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
00324 struct ieee80211_key_conf *hw_key = info->control.hw_key;
00325
00326 if (!hw_key) {
00327 if (ieee80211_wep_encrypt(tx->local, skb, tx->key->conf.key,
00328 tx->key->conf.keylen,
00329 tx->key->conf.keyidx))
00330 return -1;
00331 } else if ((hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) ||
00332 (hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) {
00333 if (!ieee80211_wep_add_iv(tx->local, skb,
00334 tx->key->conf.keylen,
00335 tx->key->conf.keyidx))
00336 return -1;
00337 }
00338
00339 return 0;
00340 }
00341
00342 ieee80211_tx_result
00343 ieee80211_crypto_wep_encrypt(struct ieee80211_tx_data *tx)
00344 {
00345 struct sk_buff *skb;
00346
00347 ieee80211_tx_set_protected(tx);
00348
00349 skb_queue_walk(&tx->skbs, skb) {
00350 if (wep_encrypt_skb(tx, skb) < 0) {
00351 I802_DEBUG_INC(tx->local->tx_handlers_drop_wep);
00352 return TX_DROP;
00353 }
00354 }
00355
00356 return TX_CONTINUE;
00357 }