Skip to content

Commit 5fdb373

Browse files
Ard Biesheuvelherbertx
authored andcommitted
net/mac80211: move WEP handling to ARC4 library interface
The WEP code in the mac80211 subsystem currently uses the crypto API to access the arc4 (RC4) cipher, which is overly complicated, and doesn't really have an upside in this particular case, since ciphers are always synchronous and therefore always implemented in software. Given that we have no accelerated software implementations either, it is much more straightforward to invoke a generic library interface directly. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
1 parent dc51f25 commit 5fdb373

File tree

11 files changed

+30
-60
lines changed

11 files changed

+30
-60
lines changed

net/mac80211/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ config MAC80211
22
tristate "Generic IEEE 802.11 Networking Stack (mac80211)"
33
depends on CFG80211
44
select CRYPTO
5-
select CRYPTO_ARC4
5+
select CRYPTO_LIB_ARC4
66
select CRYPTO_AES
77
select CRYPTO_CCM
88
select CRYPTO_GCM

net/mac80211/cfg.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/slab.h>
1616
#include <net/net_namespace.h>
1717
#include <linux/rcupdate.h>
18+
#include <linux/fips.h>
1819
#include <linux/if_ether.h>
1920
#include <net/cfg80211.h>
2021
#include "ieee80211_i.h"
@@ -403,9 +404,8 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
403404
case WLAN_CIPHER_SUITE_WEP40:
404405
case WLAN_CIPHER_SUITE_TKIP:
405406
case WLAN_CIPHER_SUITE_WEP104:
406-
if (IS_ERR(local->wep_tx_tfm))
407+
if (WARN_ON_ONCE(fips_enabled))
407408
return -EINVAL;
408-
break;
409409
case WLAN_CIPHER_SUITE_CCMP:
410410
case WLAN_CIPHER_SUITE_CCMP_256:
411411
case WLAN_CIPHER_SUITE_AES_CMAC:

net/mac80211/ieee80211_i.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,8 +1258,8 @@ struct ieee80211_local {
12581258

12591259
struct rate_control_ref *rate_ctrl;
12601260

1261-
struct crypto_cipher *wep_tx_tfm;
1262-
struct crypto_cipher *wep_rx_tfm;
1261+
struct arc4_ctx wep_tx_ctx;
1262+
struct arc4_ctx wep_rx_ctx;
12631263
u32 wep_iv;
12641264

12651265
/* see iface.c */

net/mac80211/key.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/list.h>
1515
#include <linux/crypto.h>
1616
#include <linux/rcupdate.h>
17+
#include <crypto/arc4.h>
1718
#include <net/mac80211.h>
1819

1920
#define NUM_DEFAULT_KEYS 4

net/mac80211/main.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include <net/mac80211.h>
1515
#include <linux/module.h>
16+
#include <linux/fips.h>
1617
#include <linux/init.h>
1718
#include <linux/netdevice.h>
1819
#include <linux/types.h>
@@ -733,8 +734,7 @@ EXPORT_SYMBOL(ieee80211_alloc_hw_nm);
733734

734735
static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
735736
{
736-
bool have_wep = !(IS_ERR(local->wep_tx_tfm) ||
737-
IS_ERR(local->wep_rx_tfm));
737+
bool have_wep = !fips_enabled; /* FIPS does not permit the use of RC4 */
738738
bool have_mfp = ieee80211_hw_check(&local->hw, MFP_CAPABLE);
739739
int n_suites = 0, r = 0, w = 0;
740740
u32 *suites;
@@ -1301,7 +1301,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
13011301
fail_rate:
13021302
rtnl_unlock();
13031303
ieee80211_led_exit(local);
1304-
ieee80211_wep_free(local);
13051304
fail_flows:
13061305
destroy_workqueue(local->workqueue);
13071306
fail_workqueue:
@@ -1358,7 +1357,6 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
13581357

13591358
destroy_workqueue(local->workqueue);
13601359
wiphy_unregister(local->hw.wiphy);
1361-
ieee80211_wep_free(local);
13621360
ieee80211_led_exit(local);
13631361
kfree(local->int_scan_req);
13641362
}

net/mac80211/mlme.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616

1717
#include <linux/delay.h>
18+
#include <linux/fips.h>
1819
#include <linux/if_ether.h>
1920
#include <linux/skbuff.h>
2021
#include <linux/if_arp.h>
@@ -5038,7 +5039,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
50385039
auth_alg = WLAN_AUTH_OPEN;
50395040
break;
50405041
case NL80211_AUTHTYPE_SHARED_KEY:
5041-
if (IS_ERR(local->wep_tx_tfm))
5042+
if (fips_enabled)
50425043
return -EOPNOTSUPP;
50435044
auth_alg = WLAN_AUTH_SHARED_KEY;
50445045
break;

net/mac80211/tkip.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ EXPORT_SYMBOL(ieee80211_get_tkip_p2k);
222222
* @payload_len is the length of payload (_not_ including IV/ICV length).
223223
* @ta is the transmitter addresses.
224224
*/
225-
int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm,
225+
int ieee80211_tkip_encrypt_data(struct arc4_ctx *ctx,
226226
struct ieee80211_key *key,
227227
struct sk_buff *skb,
228228
u8 *payload, size_t payload_len)
@@ -231,15 +231,15 @@ int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm,
231231

232232
ieee80211_get_tkip_p2k(&key->conf, skb, rc4key);
233233

234-
return ieee80211_wep_encrypt_data(tfm, rc4key, 16,
234+
return ieee80211_wep_encrypt_data(ctx, rc4key, 16,
235235
payload, payload_len);
236236
}
237237

238238
/* Decrypt packet payload with TKIP using @key. @pos is a pointer to the
239239
* beginning of the buffer containing IEEE 802.11 header payload, i.e.,
240240
* including IV, Ext. IV, real data, Michael MIC, ICV. @payload_len is the
241241
* length of payload, including IV, Ext. IV, MIC, ICV. */
242-
int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm,
242+
int ieee80211_tkip_decrypt_data(struct arc4_ctx *ctx,
243243
struct ieee80211_key *key,
244244
u8 *payload, size_t payload_len, u8 *ta,
245245
u8 *ra, int only_iv, int queue,
@@ -297,7 +297,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm,
297297

298298
tkip_mixing_phase2(tk, &rx_ctx->ctx, iv16, rc4key);
299299

300-
res = ieee80211_wep_decrypt_data(tfm, rc4key, 16, pos, payload_len - 12);
300+
res = ieee80211_wep_decrypt_data(ctx, rc4key, 16, pos, payload_len - 12);
301301
done:
302302
if (res == TKIP_DECRYPT_OK) {
303303
/*

net/mac80211/tkip.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
#include <linux/crypto.h>
1414
#include "key.h"
1515

16-
int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm,
16+
int ieee80211_tkip_encrypt_data(struct arc4_ctx *ctx,
1717
struct ieee80211_key *key,
1818
struct sk_buff *skb,
1919
u8 *payload, size_t payload_len);
@@ -24,7 +24,7 @@ enum {
2424
TKIP_DECRYPT_INVALID_KEYIDX = -2,
2525
TKIP_DECRYPT_REPLAY = -3,
2626
};
27-
int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm,
27+
int ieee80211_tkip_decrypt_data(struct arc4_ctx *ctx,
2828
struct ieee80211_key *key,
2929
u8 *payload, size_t payload_len, u8 *ta,
3030
u8 *ra, int only_iv, int queue,

net/mac80211/wep.c

Lines changed: 10 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -30,30 +30,9 @@ int ieee80211_wep_init(struct ieee80211_local *local)
3030
/* start WEP IV from a random value */
3131
get_random_bytes(&local->wep_iv, IEEE80211_WEP_IV_LEN);
3232

33-
local->wep_tx_tfm = crypto_alloc_cipher("arc4", 0, 0);
34-
if (IS_ERR(local->wep_tx_tfm)) {
35-
local->wep_rx_tfm = ERR_PTR(-EINVAL);
36-
return PTR_ERR(local->wep_tx_tfm);
37-
}
38-
39-
local->wep_rx_tfm = crypto_alloc_cipher("arc4", 0, 0);
40-
if (IS_ERR(local->wep_rx_tfm)) {
41-
crypto_free_cipher(local->wep_tx_tfm);
42-
local->wep_tx_tfm = ERR_PTR(-EINVAL);
43-
return PTR_ERR(local->wep_rx_tfm);
44-
}
45-
4633
return 0;
4734
}
4835

49-
void ieee80211_wep_free(struct ieee80211_local *local)
50-
{
51-
if (!IS_ERR(local->wep_tx_tfm))
52-
crypto_free_cipher(local->wep_tx_tfm);
53-
if (!IS_ERR(local->wep_rx_tfm))
54-
crypto_free_cipher(local->wep_rx_tfm);
55-
}
56-
5736
static inline bool ieee80211_wep_weak_iv(u32 iv, int keylen)
5837
{
5938
/*
@@ -131,21 +110,17 @@ static void ieee80211_wep_remove_iv(struct ieee80211_local *local,
131110
/* Perform WEP encryption using given key. data buffer must have tailroom
132111
* for 4-byte ICV. data_len must not include this ICV. Note: this function
133112
* does _not_ add IV. data = RC4(data | CRC32(data)) */
134-
int ieee80211_wep_encrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
113+
int ieee80211_wep_encrypt_data(struct arc4_ctx *ctx, u8 *rc4key,
135114
size_t klen, u8 *data, size_t data_len)
136115
{
137116
__le32 icv;
138-
int i;
139-
140-
if (IS_ERR(tfm))
141-
return -1;
142117

143118
icv = cpu_to_le32(~crc32_le(~0, data, data_len));
144119
put_unaligned(icv, (__le32 *)(data + data_len));
145120

146-
crypto_cipher_setkey(tfm, rc4key, klen);
147-
for (i = 0; i < data_len + IEEE80211_WEP_ICV_LEN; i++)
148-
crypto_cipher_encrypt_one(tfm, data + i, data + i);
121+
arc4_setkey(ctx, rc4key, klen);
122+
arc4_crypt(ctx, data, data, data_len + IEEE80211_WEP_ICV_LEN);
123+
memzero_explicit(ctx, sizeof(*ctx));
149124

150125
return 0;
151126
}
@@ -184,26 +159,22 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local,
184159
/* Add room for ICV */
185160
skb_put(skb, IEEE80211_WEP_ICV_LEN);
186161

187-
return ieee80211_wep_encrypt_data(local->wep_tx_tfm, rc4key, keylen + 3,
162+
return ieee80211_wep_encrypt_data(&local->wep_tx_ctx, rc4key, keylen + 3,
188163
iv + IEEE80211_WEP_IV_LEN, len);
189164
}
190165

191166

192167
/* Perform WEP decryption using given key. data buffer includes encrypted
193168
* payload, including 4-byte ICV, but _not_ IV. data_len must not include ICV.
194169
* Return 0 on success and -1 on ICV mismatch. */
195-
int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
170+
int ieee80211_wep_decrypt_data(struct arc4_ctx *ctx, u8 *rc4key,
196171
size_t klen, u8 *data, size_t data_len)
197172
{
198173
__le32 crc;
199-
int i;
200-
201-
if (IS_ERR(tfm))
202-
return -1;
203174

204-
crypto_cipher_setkey(tfm, rc4key, klen);
205-
for (i = 0; i < data_len + IEEE80211_WEP_ICV_LEN; i++)
206-
crypto_cipher_decrypt_one(tfm, data + i, data + i);
175+
arc4_setkey(ctx, rc4key, klen);
176+
arc4_crypt(ctx, data, data, data_len + IEEE80211_WEP_ICV_LEN);
177+
memzero_explicit(ctx, sizeof(*ctx));
207178

208179
crc = cpu_to_le32(~crc32_le(~0, data, data_len));
209180
if (memcmp(&crc, data + data_len, IEEE80211_WEP_ICV_LEN) != 0)
@@ -256,7 +227,7 @@ static int ieee80211_wep_decrypt(struct ieee80211_local *local,
256227
/* Copy rest of the WEP key (the secret part) */
257228
memcpy(rc4key + 3, key->conf.key, key->conf.keylen);
258229

259-
if (ieee80211_wep_decrypt_data(local->wep_rx_tfm, rc4key, klen,
230+
if (ieee80211_wep_decrypt_data(&local->wep_rx_ctx, rc4key, klen,
260231
skb->data + hdrlen +
261232
IEEE80211_WEP_IV_LEN, len))
262233
ret = -1;

net/mac80211/wep.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,12 @@
1717
#include "key.h"
1818

1919
int ieee80211_wep_init(struct ieee80211_local *local);
20-
void ieee80211_wep_free(struct ieee80211_local *local);
21-
int ieee80211_wep_encrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
20+
int ieee80211_wep_encrypt_data(struct arc4_ctx *ctx, u8 *rc4key,
2221
size_t klen, u8 *data, size_t data_len);
2322
int ieee80211_wep_encrypt(struct ieee80211_local *local,
2423
struct sk_buff *skb,
2524
const u8 *key, int keylen, int keyidx);
26-
int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
25+
int ieee80211_wep_decrypt_data(struct arc4_ctx *ctx, u8 *rc4key,
2726
size_t klen, u8 *data, size_t data_len);
2827

2928
ieee80211_rx_result

0 commit comments

Comments
 (0)