Skip to content

Commit

Permalink
net/lib80211: move TKIP handling to ARC4 library code
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ard Biesheuvel authored and herbertx committed Jun 20, 2019
1 parent af1f3d3 commit 4be2970
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 31 deletions.
1 change: 1 addition & 0 deletions net/wireless/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ config LIB80211_CRYPT_CCMP

config LIB80211_CRYPT_TKIP
tristate
select CRYPTO_LIB_ARC4

config LIB80211_DEBUG
bool "lib80211 debugging messages"
Expand Down
48 changes: 17 additions & 31 deletions net/wireless/lib80211_crypt_tkip.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/err.h>
#include <linux/fips.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
Expand All @@ -29,6 +30,7 @@
#include <linux/ieee80211.h>
#include <net/iw_handler.h>

#include <crypto/arc4.h>
#include <crypto/hash.h>
#include <linux/crypto.h>
#include <linux/crc32.h>
Expand Down Expand Up @@ -64,9 +66,9 @@ struct lib80211_tkip_data {

int key_idx;

struct crypto_cipher *rx_tfm_arc4;
struct arc4_ctx rx_ctx_arc4;
struct arc4_ctx tx_ctx_arc4;
struct crypto_shash *rx_tfm_michael;
struct crypto_cipher *tx_tfm_arc4;
struct crypto_shash *tx_tfm_michael;

/* scratch buffers for virt_to_page() (crypto API) */
Expand All @@ -93,30 +95,21 @@ static void *lib80211_tkip_init(int key_idx)
{
struct lib80211_tkip_data *priv;

if (fips_enabled)
return NULL;

priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
if (priv == NULL)
goto fail;

priv->key_idx = key_idx;

priv->tx_tfm_arc4 = crypto_alloc_cipher("arc4", 0, 0);
if (IS_ERR(priv->tx_tfm_arc4)) {
priv->tx_tfm_arc4 = NULL;
goto fail;
}

priv->tx_tfm_michael = crypto_alloc_shash("michael_mic", 0, 0);
if (IS_ERR(priv->tx_tfm_michael)) {
priv->tx_tfm_michael = NULL;
goto fail;
}

priv->rx_tfm_arc4 = crypto_alloc_cipher("arc4", 0, 0);
if (IS_ERR(priv->rx_tfm_arc4)) {
priv->rx_tfm_arc4 = NULL;
goto fail;
}

priv->rx_tfm_michael = crypto_alloc_shash("michael_mic", 0, 0);
if (IS_ERR(priv->rx_tfm_michael)) {
priv->rx_tfm_michael = NULL;
Expand All @@ -128,9 +121,7 @@ static void *lib80211_tkip_init(int key_idx)
fail:
if (priv) {
crypto_free_shash(priv->tx_tfm_michael);
crypto_free_cipher(priv->tx_tfm_arc4);
crypto_free_shash(priv->rx_tfm_michael);
crypto_free_cipher(priv->rx_tfm_arc4);
kfree(priv);
}

Expand All @@ -142,11 +133,9 @@ static void lib80211_tkip_deinit(void *priv)
struct lib80211_tkip_data *_priv = priv;
if (_priv) {
crypto_free_shash(_priv->tx_tfm_michael);
crypto_free_cipher(_priv->tx_tfm_arc4);
crypto_free_shash(_priv->rx_tfm_michael);
crypto_free_cipher(_priv->rx_tfm_arc4);
}
kfree(priv);
kzfree(priv);
}

static inline u16 RotR1(u16 val)
Expand Down Expand Up @@ -345,7 +334,6 @@ static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
int len;
u8 rc4key[16], *pos, *icv;
u32 crc;
int i;

if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
Expand All @@ -370,9 +358,9 @@ static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
icv[2] = crc >> 16;
icv[3] = crc >> 24;

crypto_cipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);
for (i = 0; i < len + 4; i++)
crypto_cipher_encrypt_one(tkey->tx_tfm_arc4, pos + i, pos + i);
arc4_setkey(&tkey->tx_ctx_arc4, rc4key, 16);
arc4_crypt(&tkey->tx_ctx_arc4, pos, pos, len + 4);

return 0;
}

Expand Down Expand Up @@ -400,7 +388,6 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
u8 icv[4];
u32 crc;
int plen;
int i;

hdr = (struct ieee80211_hdr *)skb->data;

Expand Down Expand Up @@ -453,9 +440,8 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)

plen = skb->len - hdr_len - 12;

crypto_cipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
for (i = 0; i < plen + 4; i++)
crypto_cipher_decrypt_one(tkey->rx_tfm_arc4, pos + i, pos + i);
arc4_setkey(&tkey->rx_ctx_arc4, rc4key, 16);
arc4_crypt(&tkey->rx_ctx_arc4, pos, pos, plen + 4);

crc = ~crc32_le(~0, pos, plen);
icv[0] = crc;
Expand Down Expand Up @@ -640,17 +626,17 @@ static int lib80211_tkip_set_key(void *key, int len, u8 * seq, void *priv)
struct lib80211_tkip_data *tkey = priv;
int keyidx;
struct crypto_shash *tfm = tkey->tx_tfm_michael;
struct crypto_cipher *tfm2 = tkey->tx_tfm_arc4;
struct arc4_ctx *tfm2 = &tkey->tx_ctx_arc4;
struct crypto_shash *tfm3 = tkey->rx_tfm_michael;
struct crypto_cipher *tfm4 = tkey->rx_tfm_arc4;
struct arc4_ctx *tfm4 = &tkey->rx_ctx_arc4;

keyidx = tkey->key_idx;
memset(tkey, 0, sizeof(*tkey));
tkey->key_idx = keyidx;
tkey->tx_tfm_michael = tfm;
tkey->tx_tfm_arc4 = tfm2;
tkey->tx_ctx_arc4 = *tfm2;
tkey->rx_tfm_michael = tfm3;
tkey->rx_tfm_arc4 = tfm4;
tkey->rx_ctx_arc4 = *tfm4;
if (len == TKIP_KEY_LEN) {
memcpy(tkey->key, key, TKIP_KEY_LEN);
tkey->key_set = 1;
Expand Down

0 comments on commit 4be2970

Please sign in to comment.