.. | .. |
---|
| 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; |
---|