| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * lib80211 crypt: host-based WEP encryption implementation for lib80211 |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (c) 2002-2004, Jouni Malinen <j@w1.fi> |
|---|
| 5 | 6 | * Copyright (c) 2008, John W. Linville <linville@tuxdriver.com> |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 8 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 9 | | - * published by the Free Software Foundation. See README and COPYING for |
|---|
| 10 | | - * more details. |
|---|
| 11 | 7 | */ |
|---|
| 12 | 8 | |
|---|
| 13 | 9 | #include <linux/err.h> |
|---|
| 10 | +#include <linux/fips.h> |
|---|
| 14 | 11 | #include <linux/module.h> |
|---|
| 15 | 12 | #include <linux/init.h> |
|---|
| 16 | 13 | #include <linux/slab.h> |
|---|
| .. | .. |
|---|
| 22 | 19 | |
|---|
| 23 | 20 | #include <net/lib80211.h> |
|---|
| 24 | 21 | |
|---|
| 25 | | -#include <crypto/skcipher.h> |
|---|
| 22 | +#include <crypto/arc4.h> |
|---|
| 26 | 23 | #include <linux/crc32.h> |
|---|
| 27 | 24 | |
|---|
| 28 | 25 | MODULE_AUTHOR("Jouni Malinen"); |
|---|
| .. | .. |
|---|
| 35 | 32 | u8 key[WEP_KEY_LEN + 1]; |
|---|
| 36 | 33 | u8 key_len; |
|---|
| 37 | 34 | u8 key_idx; |
|---|
| 38 | | - struct crypto_skcipher *tx_tfm; |
|---|
| 39 | | - struct crypto_skcipher *rx_tfm; |
|---|
| 35 | + struct arc4_ctx tx_ctx; |
|---|
| 36 | + struct arc4_ctx rx_ctx; |
|---|
| 40 | 37 | }; |
|---|
| 41 | 38 | |
|---|
| 42 | 39 | static void *lib80211_wep_init(int keyidx) |
|---|
| 43 | 40 | { |
|---|
| 44 | 41 | struct lib80211_wep_data *priv; |
|---|
| 45 | 42 | |
|---|
| 43 | + if (fips_enabled) |
|---|
| 44 | + return NULL; |
|---|
| 45 | + |
|---|
| 46 | 46 | priv = kzalloc(sizeof(*priv), GFP_ATOMIC); |
|---|
| 47 | 47 | if (priv == NULL) |
|---|
| 48 | | - goto fail; |
|---|
| 48 | + return NULL; |
|---|
| 49 | 49 | priv->key_idx = keyidx; |
|---|
| 50 | 50 | |
|---|
| 51 | | - priv->tx_tfm = crypto_alloc_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); |
|---|
| 52 | | - if (IS_ERR(priv->tx_tfm)) { |
|---|
| 53 | | - priv->tx_tfm = NULL; |
|---|
| 54 | | - goto fail; |
|---|
| 55 | | - } |
|---|
| 56 | | - |
|---|
| 57 | | - priv->rx_tfm = crypto_alloc_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); |
|---|
| 58 | | - if (IS_ERR(priv->rx_tfm)) { |
|---|
| 59 | | - priv->rx_tfm = NULL; |
|---|
| 60 | | - goto fail; |
|---|
| 61 | | - } |
|---|
| 62 | 51 | /* start WEP IV from a random value */ |
|---|
| 63 | 52 | get_random_bytes(&priv->iv, 4); |
|---|
| 64 | 53 | |
|---|
| 65 | 54 | return priv; |
|---|
| 66 | | - |
|---|
| 67 | | - fail: |
|---|
| 68 | | - if (priv) { |
|---|
| 69 | | - crypto_free_skcipher(priv->tx_tfm); |
|---|
| 70 | | - crypto_free_skcipher(priv->rx_tfm); |
|---|
| 71 | | - kfree(priv); |
|---|
| 72 | | - } |
|---|
| 73 | | - return NULL; |
|---|
| 74 | 55 | } |
|---|
| 75 | 56 | |
|---|
| 76 | 57 | static void lib80211_wep_deinit(void *priv) |
|---|
| 77 | 58 | { |
|---|
| 78 | | - struct lib80211_wep_data *_priv = priv; |
|---|
| 79 | | - if (_priv) { |
|---|
| 80 | | - crypto_free_skcipher(_priv->tx_tfm); |
|---|
| 81 | | - crypto_free_skcipher(_priv->rx_tfm); |
|---|
| 82 | | - } |
|---|
| 83 | | - kfree(priv); |
|---|
| 59 | + kfree_sensitive(priv); |
|---|
| 84 | 60 | } |
|---|
| 85 | 61 | |
|---|
| 86 | 62 | /* Add WEP IV/key info to a frame that has at least 4 bytes of headroom */ |
|---|
| .. | .. |
|---|
| 129 | 105 | static int lib80211_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) |
|---|
| 130 | 106 | { |
|---|
| 131 | 107 | struct lib80211_wep_data *wep = priv; |
|---|
| 132 | | - SKCIPHER_REQUEST_ON_STACK(req, wep->tx_tfm); |
|---|
| 133 | 108 | u32 crc, klen, len; |
|---|
| 134 | 109 | u8 *pos, *icv; |
|---|
| 135 | | - struct scatterlist sg; |
|---|
| 136 | 110 | u8 key[WEP_KEY_LEN + 3]; |
|---|
| 137 | | - int err; |
|---|
| 138 | 111 | |
|---|
| 139 | 112 | /* other checks are in lib80211_wep_build_iv */ |
|---|
| 140 | 113 | if (skb_tailroom(skb) < 4) |
|---|
| .. | .. |
|---|
| 162 | 135 | icv[2] = crc >> 16; |
|---|
| 163 | 136 | icv[3] = crc >> 24; |
|---|
| 164 | 137 | |
|---|
| 165 | | - crypto_skcipher_setkey(wep->tx_tfm, key, klen); |
|---|
| 166 | | - sg_init_one(&sg, pos, len + 4); |
|---|
| 167 | | - skcipher_request_set_tfm(req, wep->tx_tfm); |
|---|
| 168 | | - skcipher_request_set_callback(req, 0, NULL, NULL); |
|---|
| 169 | | - skcipher_request_set_crypt(req, &sg, &sg, len + 4, NULL); |
|---|
| 170 | | - err = crypto_skcipher_encrypt(req); |
|---|
| 171 | | - skcipher_request_zero(req); |
|---|
| 172 | | - return err; |
|---|
| 138 | + arc4_setkey(&wep->tx_ctx, key, klen); |
|---|
| 139 | + arc4_crypt(&wep->tx_ctx, pos, pos, len + 4); |
|---|
| 140 | + |
|---|
| 141 | + return 0; |
|---|
| 173 | 142 | } |
|---|
| 174 | 143 | |
|---|
| 175 | 144 | /* Perform WEP decryption on given buffer. Buffer includes whole WEP part of |
|---|
| .. | .. |
|---|
| 182 | 151 | static int lib80211_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) |
|---|
| 183 | 152 | { |
|---|
| 184 | 153 | struct lib80211_wep_data *wep = priv; |
|---|
| 185 | | - SKCIPHER_REQUEST_ON_STACK(req, wep->rx_tfm); |
|---|
| 186 | 154 | u32 crc, klen, plen; |
|---|
| 187 | 155 | u8 key[WEP_KEY_LEN + 3]; |
|---|
| 188 | 156 | u8 keyidx, *pos, icv[4]; |
|---|
| 189 | | - struct scatterlist sg; |
|---|
| 190 | | - int err; |
|---|
| 191 | 157 | |
|---|
| 192 | 158 | if (skb->len < hdr_len + 8) |
|---|
| 193 | 159 | return -1; |
|---|
| .. | .. |
|---|
| 208 | 174 | /* Apply RC4 to data and compute CRC32 over decrypted data */ |
|---|
| 209 | 175 | plen = skb->len - hdr_len - 8; |
|---|
| 210 | 176 | |
|---|
| 211 | | - crypto_skcipher_setkey(wep->rx_tfm, key, klen); |
|---|
| 212 | | - sg_init_one(&sg, pos, plen + 4); |
|---|
| 213 | | - skcipher_request_set_tfm(req, wep->rx_tfm); |
|---|
| 214 | | - skcipher_request_set_callback(req, 0, NULL, NULL); |
|---|
| 215 | | - skcipher_request_set_crypt(req, &sg, &sg, plen + 4, NULL); |
|---|
| 216 | | - err = crypto_skcipher_decrypt(req); |
|---|
| 217 | | - skcipher_request_zero(req); |
|---|
| 218 | | - if (err) |
|---|
| 219 | | - return -7; |
|---|
| 177 | + arc4_setkey(&wep->rx_ctx, key, klen); |
|---|
| 178 | + arc4_crypt(&wep->rx_ctx, pos, pos, plen + 4); |
|---|
| 220 | 179 | |
|---|
| 221 | 180 | crc = ~crc32_le(~0, pos, plen); |
|---|
| 222 | 181 | icv[0] = crc; |
|---|