Linux cryptographic layer development
 help / color / mirror / Atom feed
From: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
To: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Mikulas Patocka <mpatocka@redhat.com>,
	mbroz@redhat.com, dm-devel@redhat.com, agk@redhat.com,
	linux-crypto@vger.kernel.org
Subject: Re: [PATCH] crypto/arc4: convert this stream cipher into a block cipher
Date: Sun, 14 Mar 2010 09:24:32 +0100	[thread overview]
Message-ID: <20100314082432.GA1800@Chamillionaire.breakpoint.cc> (raw)
In-Reply-To: <20100223003239.GC9118@gondor.apana.org.au>

* Herbert Xu | 2010-02-23 08:32:39 [+0800]:

>If you can find a way that allows arc4 to be used by multiple
>threads at the same time while storing less than 258 bytes in
>each thread, please let me know :)
:)

>No, what you could do is structure the IV differently based on the
>flag:
>
>struct arc4_iv {
>	union {
>		struct key {
>			u8 key[256];
>			u16 keylen;
>		};
>		struct iv {
>			u8 S[256];
>			u8 x, y;
>		};
>	};
>	u8 type;
>};
>
>This relies on the fact that we never use more than 256 bytes in
>the key so limiting its length is OK.

Okay. So so are we talking about something like that below then? This is
untested and I break other users bexcept lib80211_crypt_tkip. 

the state has been moved from ctx into iv. That way encrypt()/decrypt() can
deliver the same result for a given IV. If the IV is supplied as a plain
key then it wil be converted into a different internal state.
The name is now arc4.

Signed-off-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
---
 crypto/Kconfig                       |    2 +-
 crypto/arc4.c                        |  131 +++++++++++++++++++++++-----------
 crypto/testmgr.h                     |    3 +-
 drivers/net/Kconfig                  |    1 -
 drivers/net/wireless/hostap/Kconfig  |    2 -
 drivers/net/wireless/ipw2x00/Kconfig |    2 -
 include/crypto/arc4.h                |   26 +++++++
 net/mac80211/Kconfig                 |    1 -
 net/wireless/lib80211_crypt_tkip.c   |   10 ++-
 9 files changed, 123 insertions(+), 55 deletions(-)
 create mode 100644 include/crypto/arc4.h

diff --git a/crypto/Kconfig b/crypto/Kconfig
index 81c185a..5fab1c3 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -561,7 +561,7 @@ config CRYPTO_ANUBIS
 
 config CRYPTO_ARC4
 	tristate "ARC4 cipher algorithm"
-	select CRYPTO_ALGAPI
+	select CRYPTO_BLKCIPHER
 	help
 	  ARC4 cipher algorithm.
 
diff --git a/crypto/arc4.c b/crypto/arc4.c
index 8be47e1..1b20463 100644
--- a/crypto/arc4.c
+++ b/crypto/arc4.c
@@ -1,4 +1,4 @@
-/* 
+/*
  * Cryptographic API
  *
  * ARC4 Cipher Algorithm
@@ -13,76 +13,122 @@
  */
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/crypto.h>
+#include <crypto/algapi.h>
+#include <crypto/arc4.h>
 
 #define ARC4_MIN_KEY_SIZE	1
 #define ARC4_MAX_KEY_SIZE	256
 #define ARC4_BLOCK_SIZE		1
 
-struct arc4_ctx {
-	u8 S[256];
-	u8 x, y;
-};
-
 static int arc4_set_key(struct crypto_tfm *tfm, const u8 *in_key,
 			unsigned int key_len)
 {
-	struct arc4_ctx *ctx = crypto_tfm_ctx(tfm);
+	/*
+	 * ARC4 is special: The user should supply an IV as struct arc4_iv and
+	 * fill either the key or the iv.
+	 */
+	return -EOPNOTSUPP;
+}
+
+static void arc4_key_to_iv(const u8 *in_key, u32 key_len, struct arc4_iv *iv)
+{
 	int i, j = 0, k = 0;
 
-	ctx->x = 1;
-	ctx->y = 0;
+	iv->iv.x = 1;
+	iv->iv.y = 0;
 
-	for(i = 0; i < 256; i++)
-		ctx->S[i] = i;
+	for (i = 0; i < 256; i++)
+		iv->iv.S[i] = i;
 
-	for(i = 0; i < 256; i++)
+	for (i = 0; i < 256; i++)
 	{
-		u8 a = ctx->S[i];
+		u8 a = iv->iv.S[i];
 		j = (j + in_key[k] + a) & 0xff;
-		ctx->S[i] = ctx->S[j];
-		ctx->S[j] = a;
-		if(++k >= key_len)
+		iv->iv.S[i] = iv->iv.S[j];
+		iv->iv.S[j] = a;
+		if (++k >= key_len)
 			k = 0;
 	}
-
-	return 0;
 }
 
-static void arc4_crypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+static void arc4_ivsetup(struct arc4_iv *iv)
 {
-	struct arc4_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct arc4_iv tmp_iv;
 
-	u8 *const S = ctx->S;
-	u8 x = ctx->x;
-	u8 y = ctx->y;
-	u8 a, b;
+	if (iv->type == ARC4_TYPE_IV)
+		return;
 
-	a = S[x];
-	y = (y + a) & 0xff;
-	b = S[y];
-	S[x] = b;
-	S[y] = a;
-	x = (x + 1) & 0xff;
-	*out++ = *in ^ S[(a + b) & 0xff];
+	memcpy(&tmp_iv, iv, sizeof(tmp_iv));
+	arc4_key_to_iv(tmp_iv.key.key, tmp_iv.key.key_len, iv);
+	iv->type = ARC4_TYPE_IV;
+}
+
+static int arc4_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+	struct arc4_iv *aiv;
+	u8 *S;
+	u8 x;
+	u8 y;
+	u8 a, b;
+	int ret;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	ret = blkcipher_walk_virt(desc, &walk);
+	if (ret)
+		return ret;
+
+	aiv = (struct arc4_iv *)walk.iv;
+	arc4_ivsetup(aiv);
+
+	S = aiv->iv.S;
+	x = aiv->iv.x;
+	y = aiv->iv.y;
+
+	while (walk.nbytes) {
+		u8 *in = walk.src.virt.addr;
+		u8 *out = walk.dst.virt.addr;
+		u32 i;
+
+		for (i = 0; i < walk.nbytes; i++) {
+			a = S[x];
+			y = (y + a) & 0xff;
+			b = S[y];
+			S[x] = b;
+			S[y] = a;
+			x = (x + 1) & 0xff;
+			*out = *in ^ S[(a + b) & 0xff];
+
+			in++;
+			out++;
+		}
+		ret = blkcipher_walk_done(desc, &walk, 0);
+		WARN_ON(ret < 0);
+	}
 
-	ctx->x = x;
-	ctx->y = y;
+	aiv->iv.x = x;
+	aiv->iv.y = y;
+	return ret;
 }
 
 static struct crypto_alg arc4_alg = {
 	.cra_name		=	"arc4",
-	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
+	.cra_priority		=	100,
+	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
 	.cra_blocksize		=	ARC4_BLOCK_SIZE,
-	.cra_ctxsize		=	sizeof(struct arc4_ctx),
+	.cra_ctxsize		=	0,
+	.cra_type		=	&crypto_blkcipher_type,
+	.cra_alignmask		=	3,
 	.cra_module		=	THIS_MODULE,
 	.cra_list		=	LIST_HEAD_INIT(arc4_alg.cra_list),
-	.cra_u			=	{ .cipher = {
-	.cia_min_keysize	=	ARC4_MIN_KEY_SIZE,
-	.cia_max_keysize	=	ARC4_MAX_KEY_SIZE,
-	.cia_setkey	   	= 	arc4_set_key,
-	.cia_encrypt	 	=	arc4_crypt,
-	.cia_decrypt	  	=	arc4_crypt } }
+	.cra_u			=	{ .blkcipher = {
+	.min_keysize		=	ARC4_MIN_KEY_SIZE,
+	.max_keysize		=	ARC4_MAX_KEY_SIZE,
+	.ivsize			=	sizeof(struct arc4_iv),
+	.setkey			=	arc4_set_key,
+	.encrypt		=	arc4_crypt,
+	.decrypt		=	arc4_crypt } }
 };
 
 static int __init arc4_init(void)
@@ -90,7 +136,6 @@ static int __init arc4_init(void)
 	return crypto_register_alg(&arc4_alg);
 }
 
-
 static void __exit arc4_exit(void)
 {
 	crypto_unregister_alg(&arc4_alg);
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index fb76517..423cf86 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -24,7 +24,8 @@
 #define MAX_TAP			8
 
 #define MAX_KEYLEN		56
-#define MAX_IVLEN		32
+/* sizeof arc4_iv */
+#define MAX_IVLEN		260
 
 struct hash_testvec {
 	/* only used with keyed hash algorithms */
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index dd9a09c..ddce826 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -3076,7 +3076,6 @@ config PPP_MPPE
        select CRYPTO
        select CRYPTO_SHA1
        select CRYPTO_ARC4
-       select CRYPTO_ECB
        ---help---
          Support for the MPPE Encryption protocol, as employed by the
 	 Microsoft Point-to-Point Tunneling Protocol.
diff --git a/drivers/net/wireless/hostap/Kconfig b/drivers/net/wireless/hostap/Kconfig
index 287d827..2548b56 100644
--- a/drivers/net/wireless/hostap/Kconfig
+++ b/drivers/net/wireless/hostap/Kconfig
@@ -5,10 +5,8 @@ config HOSTAP
 	select WEXT_PRIV
 	select CRYPTO
 	select CRYPTO_ARC4
-	select CRYPTO_ECB
 	select CRYPTO_AES
 	select CRYPTO_MICHAEL_MIC
-	select CRYPTO_ECB
 	select CRC32
 	select LIB80211
 	select LIB80211_CRYPT_WEP
diff --git a/drivers/net/wireless/ipw2x00/Kconfig b/drivers/net/wireless/ipw2x00/Kconfig
index 2715b10..2f2b7d9 100644
--- a/drivers/net/wireless/ipw2x00/Kconfig
+++ b/drivers/net/wireless/ipw2x00/Kconfig
@@ -159,10 +159,8 @@ config LIBIPW
 	select WEXT_SPY
 	select CRYPTO
 	select CRYPTO_ARC4
-	select CRYPTO_ECB
 	select CRYPTO_AES
 	select CRYPTO_MICHAEL_MIC
-	select CRYPTO_ECB
 	select CRC32
 	select LIB80211
 	select LIB80211_CRYPT_WEP
diff --git a/include/crypto/arc4.h b/include/crypto/arc4.h
new file mode 100644
index 0000000..1423c92
--- /dev/null
+++ b/include/crypto/arc4.h
@@ -0,0 +1,26 @@
+#ifndef __CRYPTO_ARC4_H__
+#define __CRYPTO_ARC4_H__
+
+struct arc4_iv {
+	union {
+		struct arc4_key {
+			u8 key[256];
+			u16 key_len;
+		} key;
+		struct arc4_riv {
+			u8 S[256];
+			u8 x, y;
+		} iv;
+	};
+#define ARC4_TYPE_KEY   0
+#define ARC4_TYPE_IV    1
+	u8 type;
+};
+
+static inline void arc4_setup_iv(struct arc4_iv *iv, const u8 *key, u32 len)
+{
+	memcpy(iv->key.key, key, len);
+	iv->key.key_len = len;
+	iv->type = ARC4_TYPE_KEY;
+}
+#endif
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index a10d508..7925f44 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -2,7 +2,6 @@ config MAC80211
 	tristate "Generic IEEE 802.11 Networking Stack (mac80211)"
 	depends on CFG80211
 	select CRYPTO
-	select CRYPTO_ECB
 	select CRYPTO_ARC4
 	select CRYPTO_AES
 	select CRC32
diff --git a/net/wireless/lib80211_crypt_tkip.c b/net/wireless/lib80211_crypt_tkip.c
index c362873..4c1290d 100644
--- a/net/wireless/lib80211_crypt_tkip.c
+++ b/net/wireless/lib80211_crypt_tkip.c
@@ -94,7 +94,7 @@ static void *lib80211_tkip_init(int key_idx)
 
 	priv->key_idx = key_idx;
 
-	priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
+	priv->tx_tfm_arc4 = crypto_alloc_blkcipher("arc4", 0,
 						CRYPTO_ALG_ASYNC);
 	if (IS_ERR(priv->tx_tfm_arc4)) {
 		printk(KERN_DEBUG "lib80211_crypt_tkip: could not allocate "
@@ -112,7 +112,7 @@ static void *lib80211_tkip_init(int key_idx)
 		goto fail;
 	}
 
-	priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
+	priv->rx_tfm_arc4 = crypto_alloc_blkcipher("arc4", 0,
 						CRYPTO_ALG_ASYNC);
 	if (IS_ERR(priv->rx_tfm_arc4)) {
 		printk(KERN_DEBUG "lib80211_crypt_tkip: could not allocate "
@@ -360,6 +360,7 @@ static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
 {
 	struct lib80211_tkip_data *tkey = priv;
 	struct blkcipher_desc desc = { .tfm = tkey->tx_tfm_arc4 };
+	struct arc4_iv *iv = crypto_blkcipher_crt(tkey->tx_tfm_arc4)->iv;
 	int len;
 	u8 rc4key[16], *pos, *icv;
 	u32 crc;
@@ -392,7 +393,7 @@ static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
 	icv[2] = crc >> 16;
 	icv[3] = crc >> 24;
 
-	crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);
+	arc4_setup_iv(iv, rc4key, 16);
 	sg_init_one(&sg, pos, len + 4);
 	return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
 }
@@ -414,6 +415,7 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
 {
 	struct lib80211_tkip_data *tkey = priv;
 	struct blkcipher_desc desc = { .tfm = tkey->rx_tfm_arc4 };
+	struct arc4_iv *iv = crypto_blkcipher_crt(tkey->rx_tfm_arc4)->iv;
 	u8 rc4key[16];
 	u8 keyidx, *pos;
 	u32 iv32;
@@ -485,7 +487,7 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
 
 	plen = skb->len - hdr_len - 12;
 
-	crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
+	arc4_setup_iv(iv, rc4key, 16);
 	sg_init_one(&sg, pos, plen + 4);
 	if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) {
 		if (net_ratelimit()) {
-- 
1.6.6


  reply	other threads:[~2010-03-14  8:24 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-01-25 18:29 [PATCH] dm-crypt: disable block encryption with arc4 Mikulas Patocka
2010-01-25 18:39 ` Milan Broz
2010-01-26  9:22   ` Sebastian Andrzej Siewior
2010-01-26 10:48     ` Milan Broz
2010-01-26 12:27       ` Mikulas Patocka
2010-01-26 13:34         ` Sebastian Andrzej Siewior
2010-01-26 17:11           ` Mikulas Patocka
2010-02-09  7:37         ` Herbert Xu
2010-02-09 14:02           ` Mikulas Patocka
2010-02-09 20:42             ` Herbert Xu
2010-02-09 14:57           ` Sebastian Andrzej Siewior
2010-02-09 20:45             ` Herbert Xu
2010-02-09 21:12               ` Sebastian Andrzej Siewior
2010-02-09 21:45                 ` Herbert Xu
2010-02-12  8:42                   ` [PATCH] crypto/arc4: convert this stream cipher into a block cipher Sebastian Andrzej Siewior
2010-02-12  9:34                     ` Adrian-Ken Rueegsegger
2010-02-12  9:57                       ` Sebastian Andrzej Siewior
2010-02-14 20:42                     ` Sebastian Andrzej Siewior
2010-02-15  0:10                       ` Herbert Xu
2010-02-15  8:49                         ` Sebastian Andrzej Siewior
2010-02-16 12:51                     ` Herbert Xu
2010-02-21 20:01                       ` Sebastian Andrzej Siewior
2010-02-22  0:45                         ` Herbert Xu
2010-02-22  0:52                           ` Herbert Xu
2010-02-22 22:08                             ` Sebastian Andrzej Siewior
2010-02-23  0:32                               ` Herbert Xu
2010-03-14  8:24                                 ` Sebastian Andrzej Siewior [this message]
2010-03-14  9:06                                   ` Herbert Xu
     [not found]                       ` <Pine.LNX.4.64.1002221400090.31819@hs20-bc2-1.build.redhat.com>
2010-02-23  0:15                         ` Herbert Xu
2010-01-26 12:59   ` [dm-devel] [PATCH] dm-crypt: disable block encryption with arc4 Alasdair G Kergon
2010-01-25 18:39 ` Mikulas Patocka

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100314082432.GA1800@Chamillionaire.breakpoint.cc \
    --to=sebastian@breakpoint.cc \
    --cc=agk@redhat.com \
    --cc=dm-devel@redhat.com \
    --cc=herbert@gondor.apana.org.au \
    --cc=linux-crypto@vger.kernel.org \
    --cc=mbroz@redhat.com \
    --cc=mpatocka@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox