Commit 3473187d authored by John W. Linville's avatar John W. Linville

mac80211: remove wep dependency

The current mac80211 code assumes that WEP is always available.  If WEP
fails to initialize, ieee80211_register_hw will always fail.

In some cases (e.g. FIPS certification), the cryptography used by WEP is
unavailable.  However, in such cases there is no good reason why CCMP
encryption (or even no link level encryption) cannot be used.  So, this
patch removes mac80211's assumption that WEP (and TKIP) will always be
available for use.
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 73e19463
...@@ -143,6 +143,11 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, ...@@ -143,6 +143,11 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
return -EINVAL; return -EINVAL;
} }
/* reject WEP and TKIP keys if WEP failed to initialize */
if ((alg == ALG_WEP || alg == ALG_TKIP) &&
IS_ERR(sdata->local->wep_tx_tfm))
return -EINVAL;
key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key, key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key,
params->seq_len, params->seq); params->seq_len, params->seq);
if (!key) if (!key)
......
...@@ -637,11 +637,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) ...@@ -637,11 +637,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
goto fail_sta_info; goto fail_sta_info;
result = ieee80211_wep_init(local); result = ieee80211_wep_init(local);
if (result < 0) { if (result < 0)
printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n", printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n",
wiphy_name(local->hw.wiphy), result); wiphy_name(local->hw.wiphy), result);
goto fail_wep;
}
rtnl_lock(); rtnl_lock();
...@@ -694,7 +692,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) ...@@ -694,7 +692,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
fail_rate: fail_rate:
rtnl_unlock(); rtnl_unlock();
ieee80211_wep_free(local); ieee80211_wep_free(local);
fail_wep:
sta_info_stop(local); sta_info_stop(local);
fail_sta_info: fail_sta_info:
destroy_workqueue(local->workqueue); destroy_workqueue(local->workqueue);
......
...@@ -202,7 +202,7 @@ EXPORT_SYMBOL(ieee80211_get_tkip_key); ...@@ -202,7 +202,7 @@ EXPORT_SYMBOL(ieee80211_get_tkip_key);
* @payload_len is the length of payload (_not_ including IV/ICV length). * @payload_len is the length of payload (_not_ including IV/ICV length).
* @ta is the transmitter addresses. * @ta is the transmitter addresses.
*/ */
void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, int ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm,
struct ieee80211_key *key, struct ieee80211_key *key,
u8 *pos, size_t payload_len, u8 *ta) u8 *pos, size_t payload_len, u8 *ta)
{ {
...@@ -216,7 +216,7 @@ void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, ...@@ -216,7 +216,7 @@ void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm,
tkip_mixing_phase2(tk, ctx, ctx->iv16, rc4key); tkip_mixing_phase2(tk, ctx, ctx->iv16, rc4key);
ieee80211_wep_encrypt_data(tfm, rc4key, 16, pos, payload_len); return ieee80211_wep_encrypt_data(tfm, rc4key, 16, pos, payload_len);
} }
/* Decrypt packet payload with TKIP using @key. @pos is a pointer to the /* Decrypt packet payload with TKIP using @key. @pos is a pointer to the
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key, u16 iv16); u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key, u16 iv16);
void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, int ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm,
struct ieee80211_key *key, struct ieee80211_key *key,
u8 *pos, size_t payload_len, u8 *ta); u8 *pos, size_t payload_len, u8 *ta);
enum { enum {
......
...@@ -47,7 +47,9 @@ int ieee80211_wep_init(struct ieee80211_local *local) ...@@ -47,7 +47,9 @@ int ieee80211_wep_init(struct ieee80211_local *local)
void ieee80211_wep_free(struct ieee80211_local *local) void ieee80211_wep_free(struct ieee80211_local *local)
{ {
if (!IS_ERR(local->wep_tx_tfm))
crypto_free_blkcipher(local->wep_tx_tfm); crypto_free_blkcipher(local->wep_tx_tfm);
if (!IS_ERR(local->wep_rx_tfm))
crypto_free_blkcipher(local->wep_rx_tfm); crypto_free_blkcipher(local->wep_rx_tfm);
} }
...@@ -122,19 +124,24 @@ static void ieee80211_wep_remove_iv(struct ieee80211_local *local, ...@@ -122,19 +124,24 @@ static void ieee80211_wep_remove_iv(struct ieee80211_local *local,
/* Perform WEP encryption using given key. data buffer must have tailroom /* Perform WEP encryption using given key. data buffer must have tailroom
* for 4-byte ICV. data_len must not include this ICV. Note: this function * for 4-byte ICV. data_len must not include this ICV. Note: this function
* does _not_ add IV. data = RC4(data | CRC32(data)) */ * does _not_ add IV. data = RC4(data | CRC32(data)) */
void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, int ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
size_t klen, u8 *data, size_t data_len) size_t klen, u8 *data, size_t data_len)
{ {
struct blkcipher_desc desc = { .tfm = tfm }; struct blkcipher_desc desc = { .tfm = tfm };
struct scatterlist sg; struct scatterlist sg;
__le32 icv; __le32 icv;
if (IS_ERR(tfm))
return -1;
icv = cpu_to_le32(~crc32_le(~0, data, data_len)); icv = cpu_to_le32(~crc32_le(~0, data, data_len));
put_unaligned(icv, (__le32 *)(data + data_len)); put_unaligned(icv, (__le32 *)(data + data_len));
crypto_blkcipher_setkey(tfm, rc4key, klen); crypto_blkcipher_setkey(tfm, rc4key, klen);
sg_init_one(&sg, data, data_len + WEP_ICV_LEN); sg_init_one(&sg, data, data_len + WEP_ICV_LEN);
crypto_blkcipher_encrypt(&desc, &sg, &sg, sg.length); crypto_blkcipher_encrypt(&desc, &sg, &sg, sg.length);
return 0;
} }
...@@ -168,10 +175,8 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local, ...@@ -168,10 +175,8 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local,
/* Add room for ICV */ /* Add room for ICV */
skb_put(skb, WEP_ICV_LEN); skb_put(skb, WEP_ICV_LEN);
ieee80211_wep_encrypt_data(local->wep_tx_tfm, rc4key, keylen + 3, return ieee80211_wep_encrypt_data(local->wep_tx_tfm, rc4key, keylen + 3,
iv + WEP_IV_LEN, len); iv + WEP_IV_LEN, len);
return 0;
} }
...@@ -185,6 +190,9 @@ int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, ...@@ -185,6 +190,9 @@ int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
struct scatterlist sg; struct scatterlist sg;
__le32 crc; __le32 crc;
if (IS_ERR(tfm))
return -1;
crypto_blkcipher_setkey(tfm, rc4key, klen); crypto_blkcipher_setkey(tfm, rc4key, klen);
sg_init_one(&sg, data, data_len + WEP_ICV_LEN); sg_init_one(&sg, data, data_len + WEP_ICV_LEN);
crypto_blkcipher_decrypt(&desc, &sg, &sg, sg.length); crypto_blkcipher_decrypt(&desc, &sg, &sg, sg.length);
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
int ieee80211_wep_init(struct ieee80211_local *local); int ieee80211_wep_init(struct ieee80211_local *local);
void ieee80211_wep_free(struct ieee80211_local *local); void ieee80211_wep_free(struct ieee80211_local *local);
void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, int ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
size_t klen, u8 *data, size_t data_len); size_t klen, u8 *data, size_t data_len);
int ieee80211_wep_encrypt(struct ieee80211_local *local, int ieee80211_wep_encrypt(struct ieee80211_local *local,
struct sk_buff *skb, struct sk_buff *skb,
......
...@@ -183,9 +183,8 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) ...@@ -183,9 +183,8 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
skb_put(skb, TKIP_ICV_LEN); skb_put(skb, TKIP_ICV_LEN);
hdr = (struct ieee80211_hdr *) skb->data; hdr = (struct ieee80211_hdr *) skb->data;
ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm, return ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm,
key, pos, len, hdr->addr2); key, pos, len, hdr->addr2);
return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment