mac80211: remove wep dependency
authorJohn W. Linville <linville@tuxdriver.com>
Wed, 7 Jul 2010 19:07:49 +0000 (15:07 -0400)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 8 Jul 2010 20:35:50 +0000 (16:35 -0400)
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: John W. Linville <linville@tuxdriver.com>
net/mac80211/cfg.c
net/mac80211/main.c
net/mac80211/tkip.c
net/mac80211/tkip.h
net/mac80211/wep.c
net/mac80211/wep.h
net/mac80211/wpa.c

index e55970bf2ba06f6afdb7d80988f5ffa77f51fffe..5b8b4460b69f95f69dcd9e9786bb02d2b459aaa5 100644 (file)
@@ -143,6 +143,11 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
                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,
                                  params->seq_len, params->seq);
        if (!key)
index edf7aff93268ad18670f90f9d59cca54eae1ce3a..0e95c750ded9df169bda06ab4ac9ee7ad74604ec 100644 (file)
@@ -637,11 +637,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
                goto fail_sta_info;
 
        result = ieee80211_wep_init(local);
-       if (result < 0) {
+       if (result < 0)
                printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n",
                       wiphy_name(local->hw.wiphy), result);
-               goto fail_wep;
-       }
 
        rtnl_lock();
 
@@ -694,7 +692,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
  fail_rate:
        rtnl_unlock();
        ieee80211_wep_free(local);
- fail_wep:
        sta_info_stop(local);
  fail_sta_info:
        destroy_workqueue(local->workqueue);
index 7ef491e9d66d0954aa6eba8891bcb22319f5b54b..e840c9cd46db94b122b56f2fb34bf53873585896 100644 (file)
@@ -202,9 +202,9 @@ EXPORT_SYMBOL(ieee80211_get_tkip_key);
  * @payload_len is the length of payload (_not_ including IV/ICV length).
  * @ta is the transmitter addresses.
  */
-void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm,
-                                struct ieee80211_key *key,
-                                u8 *pos, size_t payload_len, u8 *ta)
+int ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm,
+                               struct ieee80211_key *key,
+                               u8 *pos, size_t payload_len, u8 *ta)
 {
        u8 rc4key[16];
        struct tkip_ctx *ctx = &key->u.tkip.tx;
@@ -216,7 +216,7 @@ void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm,
 
        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
index d4714383f5fce5a3f5216f30669b669b8a11c1aa..7e83dee976fa0d4834ec6c09d6a0bb76b3e1123e 100644 (file)
@@ -15,7 +15,7 @@
 
 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,
                                 u8 *pos, size_t payload_len, u8 *ta);
 enum {
index 5f3a4113bda1682bb0d30f0eaebd6f153037e3b5..6d133b6efce5ac56167f03e4850cef8612a494d9 100644 (file)
@@ -47,8 +47,10 @@ int ieee80211_wep_init(struct ieee80211_local *local)
 
 void ieee80211_wep_free(struct ieee80211_local *local)
 {
-       crypto_free_blkcipher(local->wep_tx_tfm);
-       crypto_free_blkcipher(local->wep_rx_tfm);
+       if (!IS_ERR(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);
 }
 
 static inline bool ieee80211_wep_weak_iv(u32 iv, int keylen)
@@ -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
  * for 4-byte ICV. data_len must not include this ICV. Note: this function
  * does _not_ add IV. data = RC4(data | CRC32(data)) */
-void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
-                               size_t klen, u8 *data, size_t data_len)
+int ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
+                              size_t klen, u8 *data, size_t data_len)
 {
        struct blkcipher_desc desc = { .tfm = tfm };
        struct scatterlist sg;
        __le32 icv;
 
+       if (IS_ERR(tfm))
+               return -1;
+
        icv = cpu_to_le32(~crc32_le(~0, data, data_len));
        put_unaligned(icv, (__le32 *)(data + data_len));
 
        crypto_blkcipher_setkey(tfm, rc4key, klen);
        sg_init_one(&sg, data, data_len + WEP_ICV_LEN);
        crypto_blkcipher_encrypt(&desc, &sg, &sg, sg.length);
+
+       return 0;
 }
 
 
@@ -168,10 +175,8 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local,
        /* Add room for ICV */
        skb_put(skb, WEP_ICV_LEN);
 
-       ieee80211_wep_encrypt_data(local->wep_tx_tfm, rc4key, keylen + 3,
-                                  iv + WEP_IV_LEN, len);
-
-       return 0;
+       return ieee80211_wep_encrypt_data(local->wep_tx_tfm, rc4key, keylen + 3,
+                                         iv + WEP_IV_LEN, len);
 }
 
 
@@ -185,6 +190,9 @@ int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
        struct scatterlist sg;
        __le32 crc;
 
+       if (IS_ERR(tfm))
+               return -1;
+
        crypto_blkcipher_setkey(tfm, rc4key, klen);
        sg_init_one(&sg, data, data_len + WEP_ICV_LEN);
        crypto_blkcipher_decrypt(&desc, &sg, &sg, sg.length);
index fe29d7e5759fe3704658afb430b7e071921a21d0..58654ee335186d2a3d0f588221dd62d22cf4cf0d 100644 (file)
@@ -18,7 +18,7 @@
 
 int ieee80211_wep_init(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);
 int ieee80211_wep_encrypt(struct ieee80211_local *local,
                          struct sk_buff *skb,
index a14e67707476ac4e7cb4e1f24b6ce77b2cc57969..8d59d27d887e3a0b96d9d995e3138595f0a13c79 100644 (file)
@@ -183,9 +183,8 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
        skb_put(skb, TKIP_ICV_LEN);
 
        hdr = (struct ieee80211_hdr *) skb->data;
-       ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm,
-                                   key, pos, len, hdr->addr2);
-       return 0;
+       return ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm,
+                                          key, pos, len, hdr->addr2);
 }