diff options
author | Ard Biesheuvel <ard.biesheuvel@linaro.org> | 2019-06-12 12:19:56 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2019-06-20 02:18:33 -0400 |
commit | 4be297016cd3a6aedbcc3b053da16cdd42546f04 (patch) | |
tree | 0c1c5e88b5dfd15e33bc6aab30fb3667e56247d4 | |
parent | af1f3d327d49d9bb94d9c173023e6cbdc5453d38 (diff) |
net/lib80211: move TKIP handling to ARC4 library code
The crypto API abstraction is not very useful for invoking ciphers
directly, especially in the case of arc4, which only has a generic
implementation in C. So let's invoke the library code directly.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r-- | net/wireless/Kconfig | 1 | ||||
-rw-r--r-- | net/wireless/lib80211_crypt_tkip.c | 48 |
2 files changed, 18 insertions, 31 deletions
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index abff3c6a5b50..2cfc5b7800e9 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig | |||
@@ -219,6 +219,7 @@ config LIB80211_CRYPT_CCMP | |||
219 | 219 | ||
220 | config LIB80211_CRYPT_TKIP | 220 | config LIB80211_CRYPT_TKIP |
221 | tristate | 221 | tristate |
222 | select CRYPTO_LIB_ARC4 | ||
222 | 223 | ||
223 | config LIB80211_DEBUG | 224 | config LIB80211_DEBUG |
224 | bool "lib80211 debugging messages" | 225 | bool "lib80211 debugging messages" |
diff --git a/net/wireless/lib80211_crypt_tkip.c b/net/wireless/lib80211_crypt_tkip.c index 11eaa5956f00..0fd155c4e0a6 100644 --- a/net/wireless/lib80211_crypt_tkip.c +++ b/net/wireless/lib80211_crypt_tkip.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
14 | 14 | ||
15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
16 | #include <linux/fips.h> | ||
16 | #include <linux/module.h> | 17 | #include <linux/module.h> |
17 | #include <linux/init.h> | 18 | #include <linux/init.h> |
18 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
@@ -29,6 +30,7 @@ | |||
29 | #include <linux/ieee80211.h> | 30 | #include <linux/ieee80211.h> |
30 | #include <net/iw_handler.h> | 31 | #include <net/iw_handler.h> |
31 | 32 | ||
33 | #include <crypto/arc4.h> | ||
32 | #include <crypto/hash.h> | 34 | #include <crypto/hash.h> |
33 | #include <linux/crypto.h> | 35 | #include <linux/crypto.h> |
34 | #include <linux/crc32.h> | 36 | #include <linux/crc32.h> |
@@ -64,9 +66,9 @@ struct lib80211_tkip_data { | |||
64 | 66 | ||
65 | int key_idx; | 67 | int key_idx; |
66 | 68 | ||
67 | struct crypto_cipher *rx_tfm_arc4; | 69 | struct arc4_ctx rx_ctx_arc4; |
70 | struct arc4_ctx tx_ctx_arc4; | ||
68 | struct crypto_shash *rx_tfm_michael; | 71 | struct crypto_shash *rx_tfm_michael; |
69 | struct crypto_cipher *tx_tfm_arc4; | ||
70 | struct crypto_shash *tx_tfm_michael; | 72 | struct crypto_shash *tx_tfm_michael; |
71 | 73 | ||
72 | /* scratch buffers for virt_to_page() (crypto API) */ | 74 | /* scratch buffers for virt_to_page() (crypto API) */ |
@@ -93,30 +95,21 @@ static void *lib80211_tkip_init(int key_idx) | |||
93 | { | 95 | { |
94 | struct lib80211_tkip_data *priv; | 96 | struct lib80211_tkip_data *priv; |
95 | 97 | ||
98 | if (fips_enabled) | ||
99 | return NULL; | ||
100 | |||
96 | priv = kzalloc(sizeof(*priv), GFP_ATOMIC); | 101 | priv = kzalloc(sizeof(*priv), GFP_ATOMIC); |
97 | if (priv == NULL) | 102 | if (priv == NULL) |
98 | goto fail; | 103 | goto fail; |
99 | 104 | ||
100 | priv->key_idx = key_idx; | 105 | priv->key_idx = key_idx; |
101 | 106 | ||
102 | priv->tx_tfm_arc4 = crypto_alloc_cipher("arc4", 0, 0); | ||
103 | if (IS_ERR(priv->tx_tfm_arc4)) { | ||
104 | priv->tx_tfm_arc4 = NULL; | ||
105 | goto fail; | ||
106 | } | ||
107 | |||
108 | priv->tx_tfm_michael = crypto_alloc_shash("michael_mic", 0, 0); | 107 | priv->tx_tfm_michael = crypto_alloc_shash("michael_mic", 0, 0); |
109 | if (IS_ERR(priv->tx_tfm_michael)) { | 108 | if (IS_ERR(priv->tx_tfm_michael)) { |
110 | priv->tx_tfm_michael = NULL; | 109 | priv->tx_tfm_michael = NULL; |
111 | goto fail; | 110 | goto fail; |
112 | } | 111 | } |
113 | 112 | ||
114 | priv->rx_tfm_arc4 = crypto_alloc_cipher("arc4", 0, 0); | ||
115 | if (IS_ERR(priv->rx_tfm_arc4)) { | ||
116 | priv->rx_tfm_arc4 = NULL; | ||
117 | goto fail; | ||
118 | } | ||
119 | |||
120 | priv->rx_tfm_michael = crypto_alloc_shash("michael_mic", 0, 0); | 113 | priv->rx_tfm_michael = crypto_alloc_shash("michael_mic", 0, 0); |
121 | if (IS_ERR(priv->rx_tfm_michael)) { | 114 | if (IS_ERR(priv->rx_tfm_michael)) { |
122 | priv->rx_tfm_michael = NULL; | 115 | priv->rx_tfm_michael = NULL; |
@@ -128,9 +121,7 @@ static void *lib80211_tkip_init(int key_idx) | |||
128 | fail: | 121 | fail: |
129 | if (priv) { | 122 | if (priv) { |
130 | crypto_free_shash(priv->tx_tfm_michael); | 123 | crypto_free_shash(priv->tx_tfm_michael); |
131 | crypto_free_cipher(priv->tx_tfm_arc4); | ||
132 | crypto_free_shash(priv->rx_tfm_michael); | 124 | crypto_free_shash(priv->rx_tfm_michael); |
133 | crypto_free_cipher(priv->rx_tfm_arc4); | ||
134 | kfree(priv); | 125 | kfree(priv); |
135 | } | 126 | } |
136 | 127 | ||
@@ -142,11 +133,9 @@ static void lib80211_tkip_deinit(void *priv) | |||
142 | struct lib80211_tkip_data *_priv = priv; | 133 | struct lib80211_tkip_data *_priv = priv; |
143 | if (_priv) { | 134 | if (_priv) { |
144 | crypto_free_shash(_priv->tx_tfm_michael); | 135 | crypto_free_shash(_priv->tx_tfm_michael); |
145 | crypto_free_cipher(_priv->tx_tfm_arc4); | ||
146 | crypto_free_shash(_priv->rx_tfm_michael); | 136 | crypto_free_shash(_priv->rx_tfm_michael); |
147 | crypto_free_cipher(_priv->rx_tfm_arc4); | ||
148 | } | 137 | } |
149 | kfree(priv); | 138 | kzfree(priv); |
150 | } | 139 | } |
151 | 140 | ||
152 | static inline u16 RotR1(u16 val) | 141 | static inline u16 RotR1(u16 val) |
@@ -345,7 +334,6 @@ static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
345 | int len; | 334 | int len; |
346 | u8 rc4key[16], *pos, *icv; | 335 | u8 rc4key[16], *pos, *icv; |
347 | u32 crc; | 336 | u32 crc; |
348 | int i; | ||
349 | 337 | ||
350 | if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) { | 338 | if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) { |
351 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 339 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
@@ -370,9 +358,9 @@ static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
370 | icv[2] = crc >> 16; | 358 | icv[2] = crc >> 16; |
371 | icv[3] = crc >> 24; | 359 | icv[3] = crc >> 24; |
372 | 360 | ||
373 | crypto_cipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); | 361 | arc4_setkey(&tkey->tx_ctx_arc4, rc4key, 16); |
374 | for (i = 0; i < len + 4; i++) | 362 | arc4_crypt(&tkey->tx_ctx_arc4, pos, pos, len + 4); |
375 | crypto_cipher_encrypt_one(tkey->tx_tfm_arc4, pos + i, pos + i); | 363 | |
376 | return 0; | 364 | return 0; |
377 | } | 365 | } |
378 | 366 | ||
@@ -400,7 +388,6 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
400 | u8 icv[4]; | 388 | u8 icv[4]; |
401 | u32 crc; | 389 | u32 crc; |
402 | int plen; | 390 | int plen; |
403 | int i; | ||
404 | 391 | ||
405 | hdr = (struct ieee80211_hdr *)skb->data; | 392 | hdr = (struct ieee80211_hdr *)skb->data; |
406 | 393 | ||
@@ -453,9 +440,8 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
453 | 440 | ||
454 | plen = skb->len - hdr_len - 12; | 441 | plen = skb->len - hdr_len - 12; |
455 | 442 | ||
456 | crypto_cipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); | 443 | arc4_setkey(&tkey->rx_ctx_arc4, rc4key, 16); |
457 | for (i = 0; i < plen + 4; i++) | 444 | arc4_crypt(&tkey->rx_ctx_arc4, pos, pos, plen + 4); |
458 | crypto_cipher_decrypt_one(tkey->rx_tfm_arc4, pos + i, pos + i); | ||
459 | 445 | ||
460 | crc = ~crc32_le(~0, pos, plen); | 446 | crc = ~crc32_le(~0, pos, plen); |
461 | icv[0] = crc; | 447 | icv[0] = crc; |
@@ -640,17 +626,17 @@ static int lib80211_tkip_set_key(void *key, int len, u8 * seq, void *priv) | |||
640 | struct lib80211_tkip_data *tkey = priv; | 626 | struct lib80211_tkip_data *tkey = priv; |
641 | int keyidx; | 627 | int keyidx; |
642 | struct crypto_shash *tfm = tkey->tx_tfm_michael; | 628 | struct crypto_shash *tfm = tkey->tx_tfm_michael; |
643 | struct crypto_cipher *tfm2 = tkey->tx_tfm_arc4; | 629 | struct arc4_ctx *tfm2 = &tkey->tx_ctx_arc4; |
644 | struct crypto_shash *tfm3 = tkey->rx_tfm_michael; | 630 | struct crypto_shash *tfm3 = tkey->rx_tfm_michael; |
645 | struct crypto_cipher *tfm4 = tkey->rx_tfm_arc4; | 631 | struct arc4_ctx *tfm4 = &tkey->rx_ctx_arc4; |
646 | 632 | ||
647 | keyidx = tkey->key_idx; | 633 | keyidx = tkey->key_idx; |
648 | memset(tkey, 0, sizeof(*tkey)); | 634 | memset(tkey, 0, sizeof(*tkey)); |
649 | tkey->key_idx = keyidx; | 635 | tkey->key_idx = keyidx; |
650 | tkey->tx_tfm_michael = tfm; | 636 | tkey->tx_tfm_michael = tfm; |
651 | tkey->tx_tfm_arc4 = tfm2; | 637 | tkey->tx_ctx_arc4 = *tfm2; |
652 | tkey->rx_tfm_michael = tfm3; | 638 | tkey->rx_tfm_michael = tfm3; |
653 | tkey->rx_tfm_arc4 = tfm4; | 639 | tkey->rx_ctx_arc4 = *tfm4; |
654 | if (len == TKIP_KEY_LEN) { | 640 | if (len == TKIP_KEY_LEN) { |
655 | memcpy(tkey->key, key, TKIP_KEY_LEN); | 641 | memcpy(tkey->key, key, TKIP_KEY_LEN); |
656 | tkey->key_set = 1; | 642 | tkey->key_set = 1; |