tristate "Generic IEEE 802.11 Networking Stack (mac80211)"
        depends on CFG80211
        select CRYPTO
-       select CRYPTO_ARC4
+       select CRYPTO_LIB_ARC4
        select CRYPTO_AES
        select CRYPTO_CCM
        select CRYPTO_GCM
 
 #include <linux/slab.h>
 #include <net/net_namespace.h>
 #include <linux/rcupdate.h>
+#include <linux/fips.h>
 #include <linux/if_ether.h>
 #include <net/cfg80211.h>
 #include "ieee80211_i.h"
        case WLAN_CIPHER_SUITE_WEP40:
        case WLAN_CIPHER_SUITE_TKIP:
        case WLAN_CIPHER_SUITE_WEP104:
-               if (IS_ERR(local->wep_tx_tfm))
+               if (WARN_ON_ONCE(fips_enabled))
                        return -EINVAL;
-               break;
        case WLAN_CIPHER_SUITE_CCMP:
        case WLAN_CIPHER_SUITE_CCMP_256:
        case WLAN_CIPHER_SUITE_AES_CMAC:
 
 
        struct rate_control_ref *rate_ctrl;
 
-       struct crypto_cipher *wep_tx_tfm;
-       struct crypto_cipher *wep_rx_tfm;
+       struct arc4_ctx wep_tx_ctx;
+       struct arc4_ctx wep_rx_ctx;
        u32 wep_iv;
 
        /* see iface.c */
 
 #include <linux/list.h>
 #include <linux/crypto.h>
 #include <linux/rcupdate.h>
+#include <crypto/arc4.h>
 #include <net/mac80211.h>
 
 #define NUM_DEFAULT_KEYS 4
 
 
 #include <net/mac80211.h>
 #include <linux/module.h>
+#include <linux/fips.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/types.h>
 
 static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
 {
-       bool have_wep = !(IS_ERR(local->wep_tx_tfm) ||
-                         IS_ERR(local->wep_rx_tfm));
+       bool have_wep = !fips_enabled; /* FIPS does not permit the use of RC4 */
        bool have_mfp = ieee80211_hw_check(&local->hw, MFP_CAPABLE);
        int n_suites = 0, r = 0, w = 0;
        u32 *suites;
  fail_rate:
        rtnl_unlock();
        ieee80211_led_exit(local);
-       ieee80211_wep_free(local);
  fail_flows:
        destroy_workqueue(local->workqueue);
  fail_workqueue:
 
        destroy_workqueue(local->workqueue);
        wiphy_unregister(local->hw.wiphy);
-       ieee80211_wep_free(local);
        ieee80211_led_exit(local);
        kfree(local->int_scan_req);
 }
 
  */
 
 #include <linux/delay.h>
+#include <linux/fips.h>
 #include <linux/if_ether.h>
 #include <linux/skbuff.h>
 #include <linux/if_arp.h>
                auth_alg = WLAN_AUTH_OPEN;
                break;
        case NL80211_AUTHTYPE_SHARED_KEY:
-               if (IS_ERR(local->wep_tx_tfm))
+               if (fips_enabled)
                        return -EOPNOTSUPP;
                auth_alg = WLAN_AUTH_SHARED_KEY;
                break;
 
  * @payload_len is the length of payload (_not_ including IV/ICV length).
  * @ta is the transmitter addresses.
  */
-int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm,
+int ieee80211_tkip_encrypt_data(struct arc4_ctx *ctx,
                                struct ieee80211_key *key,
                                struct sk_buff *skb,
                                u8 *payload, size_t payload_len)
 
        ieee80211_get_tkip_p2k(&key->conf, skb, rc4key);
 
-       return ieee80211_wep_encrypt_data(tfm, rc4key, 16,
+       return ieee80211_wep_encrypt_data(ctx, rc4key, 16,
                                          payload, payload_len);
 }
 
  * beginning of the buffer containing IEEE 802.11 header payload, i.e.,
  * including IV, Ext. IV, real data, Michael MIC, ICV. @payload_len is the
  * length of payload, including IV, Ext. IV, MIC, ICV.  */
-int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm,
+int ieee80211_tkip_decrypt_data(struct arc4_ctx *ctx,
                                struct ieee80211_key *key,
                                u8 *payload, size_t payload_len, u8 *ta,
                                u8 *ra, int only_iv, int queue,
 
        tkip_mixing_phase2(tk, &rx_ctx->ctx, iv16, rc4key);
 
-       res = ieee80211_wep_decrypt_data(tfm, rc4key, 16, pos, payload_len - 12);
+       res = ieee80211_wep_decrypt_data(ctx, rc4key, 16, pos, payload_len - 12);
  done:
        if (res == TKIP_DECRYPT_OK) {
                /*
 
 #include <linux/crypto.h>
 #include "key.h"
 
-int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm,
+int ieee80211_tkip_encrypt_data(struct arc4_ctx *ctx,
                                struct ieee80211_key *key,
                                struct sk_buff *skb,
                                u8 *payload, size_t payload_len);
        TKIP_DECRYPT_INVALID_KEYIDX = -2,
        TKIP_DECRYPT_REPLAY = -3,
 };
-int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm,
+int ieee80211_tkip_decrypt_data(struct arc4_ctx *ctx,
                                struct ieee80211_key *key,
                                u8 *payload, size_t payload_len, u8 *ta,
                                u8 *ra, int only_iv, int queue,
 
        /* start WEP IV from a random value */
        get_random_bytes(&local->wep_iv, IEEE80211_WEP_IV_LEN);
 
-       local->wep_tx_tfm = crypto_alloc_cipher("arc4", 0, 0);
-       if (IS_ERR(local->wep_tx_tfm)) {
-               local->wep_rx_tfm = ERR_PTR(-EINVAL);
-               return PTR_ERR(local->wep_tx_tfm);
-       }
-
-       local->wep_rx_tfm = crypto_alloc_cipher("arc4", 0, 0);
-       if (IS_ERR(local->wep_rx_tfm)) {
-               crypto_free_cipher(local->wep_tx_tfm);
-               local->wep_tx_tfm = ERR_PTR(-EINVAL);
-               return PTR_ERR(local->wep_rx_tfm);
-       }
-
        return 0;
 }
 
-void ieee80211_wep_free(struct ieee80211_local *local)
-{
-       if (!IS_ERR(local->wep_tx_tfm))
-               crypto_free_cipher(local->wep_tx_tfm);
-       if (!IS_ERR(local->wep_rx_tfm))
-               crypto_free_cipher(local->wep_rx_tfm);
-}
-
 static inline bool ieee80211_wep_weak_iv(u32 iv, int keylen)
 {
        /*
 /* 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)) */
-int ieee80211_wep_encrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
+int ieee80211_wep_encrypt_data(struct arc4_ctx *ctx, u8 *rc4key,
                               size_t klen, u8 *data, size_t data_len)
 {
        __le32 icv;
-       int i;
-
-       if (IS_ERR(tfm))
-               return -1;
 
        icv = cpu_to_le32(~crc32_le(~0, data, data_len));
        put_unaligned(icv, (__le32 *)(data + data_len));
 
-       crypto_cipher_setkey(tfm, rc4key, klen);
-       for (i = 0; i < data_len + IEEE80211_WEP_ICV_LEN; i++)
-               crypto_cipher_encrypt_one(tfm, data + i, data + i);
+       arc4_setkey(ctx, rc4key, klen);
+       arc4_crypt(ctx, data, data, data_len + IEEE80211_WEP_ICV_LEN);
+       memzero_explicit(ctx, sizeof(*ctx));
 
        return 0;
 }
        /* Add room for ICV */
        skb_put(skb, IEEE80211_WEP_ICV_LEN);
 
-       return ieee80211_wep_encrypt_data(local->wep_tx_tfm, rc4key, keylen + 3,
+       return ieee80211_wep_encrypt_data(&local->wep_tx_ctx, rc4key, keylen + 3,
                                          iv + IEEE80211_WEP_IV_LEN, len);
 }
 
 /* Perform WEP decryption using given key. data buffer includes encrypted
  * payload, including 4-byte ICV, but _not_ IV. data_len must not include ICV.
  * Return 0 on success and -1 on ICV mismatch. */
-int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
+int ieee80211_wep_decrypt_data(struct arc4_ctx *ctx, u8 *rc4key,
                               size_t klen, u8 *data, size_t data_len)
 {
        __le32 crc;
-       int i;
-
-       if (IS_ERR(tfm))
-               return -1;
 
-       crypto_cipher_setkey(tfm, rc4key, klen);
-       for (i = 0; i < data_len + IEEE80211_WEP_ICV_LEN; i++)
-               crypto_cipher_decrypt_one(tfm, data + i, data + i);
+       arc4_setkey(ctx, rc4key, klen);
+       arc4_crypt(ctx, data, data, data_len + IEEE80211_WEP_ICV_LEN);
+       memzero_explicit(ctx, sizeof(*ctx));
 
        crc = cpu_to_le32(~crc32_le(~0, data, data_len));
        if (memcmp(&crc, data + data_len, IEEE80211_WEP_ICV_LEN) != 0)
        /* Copy rest of the WEP key (the secret part) */
        memcpy(rc4key + 3, key->conf.key, key->conf.keylen);
 
-       if (ieee80211_wep_decrypt_data(local->wep_rx_tfm, rc4key, klen,
+       if (ieee80211_wep_decrypt_data(&local->wep_rx_ctx, rc4key, klen,
                                       skb->data + hdrlen +
                                       IEEE80211_WEP_IV_LEN, len))
                ret = -1;
 
 #include "key.h"
 
 int ieee80211_wep_init(struct ieee80211_local *local);
-void ieee80211_wep_free(struct ieee80211_local *local);
-int ieee80211_wep_encrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
+int ieee80211_wep_encrypt_data(struct arc4_ctx *ctx, u8 *rc4key,
                                size_t klen, u8 *data, size_t data_len);
 int ieee80211_wep_encrypt(struct ieee80211_local *local,
                          struct sk_buff *skb,
                          const u8 *key, int keylen, int keyidx);
-int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
+int ieee80211_wep_decrypt_data(struct arc4_ctx *ctx, u8 *rc4key,
                               size_t klen, u8 *data, size_t data_len);
 
 ieee80211_rx_result
 
        /* Add room for ICV */
        skb_put(skb, IEEE80211_TKIP_ICV_LEN);
 
-       return ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm,
+       return ieee80211_tkip_encrypt_data(&tx->local->wep_tx_ctx,
                                           key, skb, pos, len);
 }
 
        if (status->flag & RX_FLAG_DECRYPTED)
                hwaccel = 1;
 
-       res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm,
+       res = ieee80211_tkip_decrypt_data(&rx->local->wep_rx_ctx,
                                          key, skb->data + hdrlen,
                                          skb->len - hdrlen, rx->sta->sta.addr,
                                          hdr->addr1, hwaccel, rx->security_idx,