LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH 2/2] Support for VIA PadLock crypto engine
@ 2004-05-10 14:40 Michal Ludvig
  2004-05-10 15:55 ` James Morris
  0 siblings, 1 reply; 24+ messages in thread
From: Michal Ludvig @ 2004-05-10 14:40 UTC (permalink / raw)
  To: Andrew Morton; +Cc: David S. Miller, linux-kernel

Hi,

this is the second part of the patch that enables use of the hardware
cryptography engine in VIA C3 Nehemiah CPUs (so called PadLock ACE)
for AES algorithm.

It adds two new config options in the Cryptography section and if
these are selected, aes.ko is built with the support for PadLock ACE.
It can always be disabled with 'disable_via_padlock=1' module option
in this case, or if the PadLock is not found in the CPU, aes.ko
reverts to the software encryption.

 Kconfig |   20 ++++
 aes.c   |  296 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 307 insertions(+), 9 deletions(-)

Please apply.

Michal Ludvig

diff -urp linux-2.6.5.patched/crypto/Kconfig linux-2.6.5/crypto/Kconfig
--- linux-2.6.5.patched/crypto/Kconfig	2004-04-29 10:33:05.000000000 +0200
+++ linux-2.6.5/crypto/Kconfig	2004-05-10 09:03:47.000000000 +0200
@@ -9,6 +9,19 @@ config CRYPTO
 	help
 	  This option provides the core Cryptographic API.

+config CRYPTO_VIA_PADLOCK
+	bool "Support for VIA PadLock ACE"
+	depends on CRYPTO && X86 && !X86_64
+	help
+	  Some VIA processors come with an integrated crypto engine
+	  (so called VIA PadLock ACE, Advanced Cryptography Engine)
+	  that provides instructions for very fast {en,de}cryption
+	  with some algorithms.
+
+	  The instructions are used only when the CPU supports them.
+	  Otherwise software encryption is used. If you are unsure,
+	  say Y.
+
 config CRYPTO_HMAC
 	bool "HMAC support"
 	depends on CRYPTO
@@ -126,6 +139,13 @@ config CRYPTO_AES

 	  See http://csrc.nist.gov/CryptoToolkit/aes/ for more information.

+config CRYPTO_AES_PADLOCK
+	bool "Support for AES in VIA PadLock"
+	depends on CRYPTO_AES && CRYPTO_VIA_PADLOCK
+	default y
+	help
+	  Use VIA PadLock for AES algorithm.
+
 config CRYPTO_CAST5
 	tristate "CAST5 (CAST-128) cipher algorithm"
 	depends on CRYPTO
diff -urp linux-2.6.5.patched/crypto/aes.c linux-2.6.5/crypto/aes.c
--- linux-2.6.5.patched/crypto/aes.c	2004-04-29 10:33:05.000000000 +0200
+++ linux-2.6.5/crypto/aes.c	2004-05-10 15:20:14.808278600 +0200
@@ -10,6 +10,7 @@
  *  Herbert Valerio Riedel <hvr@hvrlab.org>
  *  Kyle McMartin <kyle@debian.org>
  *  Adam J. Richter <adam@yggdrasil.com> (conversion to 2.5 API).
+ *  Michal Ludvig <mludvig@suse.cz> (support for VIA PadLock)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -59,10 +60,18 @@
 #include <linux/crypto.h>
 #include <asm/byteorder.h>

-#define AES_MIN_KEY_SIZE	16
-#define AES_MAX_KEY_SIZE	32
-
-#define AES_BLOCK_SIZE		16
+#define AES_MIN_KEY_SIZE	16	/* in u8 units */
+#define AES_MAX_KEY_SIZE	32	/* ditto */
+#define AES_BLOCK_SIZE		16	/* ditto */
+#define AES_EXTENDED_KEY_SIZE	64	/* in u32 units */
+#define AES_EXTENDED_KEY_SIZE_B	(AES_EXTENDED_KEY_SIZE * sizeof(u32))
+
+#define PFX	"aes: "
+
+#ifdef CONFIG_CRYPTO_AES_PADLOCK
+	static u8 use_padlock;
+	static inline int padlock_hw_extkey_available (u8 key_len);
+#endif

 static inline
 u32 generic_rotr32 (const u32 x, const unsigned bits)
@@ -94,9 +103,11 @@ byte(const u32 x, const unsigned n)
 #define u32_out(to, from) (*(u32 *)(to) = cpu_to_le32(from))

 struct aes_ctx {
+	u32 e_data[AES_EXTENDED_KEY_SIZE+4];
+	u32 d_data[AES_EXTENDED_KEY_SIZE+4];
 	int key_length;
-	u32 E[60];
-	u32 D[60];
+	u32 *E;
+	u32 *D;
 };

 #define E_KEY ctx->E
@@ -274,6 +285,10 @@ aes_set_key(void *ctx_arg, const u8 *in_
 {
 	struct aes_ctx *ctx = ctx_arg;
 	u32 i, t, u, v, w;
+#ifdef CONFIG_CRYPTO_AES_PADLOCK
+	u32 P[AES_EXTENDED_KEY_SIZE];
+	u32 rounds;
+#endif

 	if (key_len != 16 && key_len != 24 && key_len != 32) {
 		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
@@ -282,11 +297,31 @@ aes_set_key(void *ctx_arg, const u8 *in_

 	ctx->key_length = key_len;

+	ctx->E = ctx->e_data;
+	ctx->D = ctx->d_data;
+
+#ifdef CONFIG_CRYPTO_AES_PADLOCK
+	if (use_padlock) {
+		/* Ensure 16-Bytes alignmentation of keys for VIA PadLock. */
+		if ((int)(ctx->e_data) & 0x0F)
+			ctx->E += 4 - (((int)(ctx->e_data) & 0x0F) / sizeof (ctx->e_data[0]));
+
+		if ((int)(ctx->d_data) & 0x0F)
+			ctx->D += 4 - (((int)(ctx->d_data) & 0x0F) / sizeof (ctx->d_data[0]));
+	}
+#endif
+
 	E_KEY[0] = u32_in (in_key);
 	E_KEY[1] = u32_in (in_key + 4);
 	E_KEY[2] = u32_in (in_key + 8);
 	E_KEY[3] = u32_in (in_key + 12);

+#ifdef CONFIG_CRYPTO_AES_PADLOCK
+	/* Don't generate extended keys if the hardware can do it. */
+	if (use_padlock && padlock_hw_extkey_available(key_len))
+		return 0;
+#endif
+
 	switch (key_len) {
 	case 16:
 		t = E_KEY[3];
@@ -320,6 +355,27 @@ aes_set_key(void *ctx_arg, const u8 *in_
 		imix_col (D_KEY[i], E_KEY[i]);
 	}

+#ifdef CONFIG_CRYPTO_AES_PADLOCK
+	if (use_padlock) {
+		/* PadLock needs a different format of the decryption key. */
+		rounds = 10 + (key_len - 16) / 4;
+
+		for (i = 0; i < rounds; i++) {
+			P[((i + 1) * 4) + 0] = D_KEY[((rounds - i - 1) * 4) + 0];
+			P[((i + 1) * 4) + 1] = D_KEY[((rounds - i - 1) * 4) + 1];
+			P[((i + 1) * 4) + 2] = D_KEY[((rounds - i - 1) * 4) + 2];
+			P[((i + 1) * 4) + 3] = D_KEY[((rounds - i - 1) * 4) + 3];
+		}
+
+		P[0] = E_KEY[(rounds * 4) + 0];
+		P[1] = E_KEY[(rounds * 4) + 1];
+		P[2] = E_KEY[(rounds * 4) + 2];
+		P[3] = E_KEY[(rounds * 4) + 3];
+
+		memcpy(D_KEY, P, AES_EXTENDED_KEY_SIZE_B);
+	}
+#endif
+
 	return 0;
 }

@@ -338,7 +394,7 @@ aes_set_key(void *ctx_arg, const u8 *in_
     f_rl(bo, bi, 2, k);     \
     f_rl(bo, bi, 3, k)

-static void aes_encrypt(void *ctx_arg, u8 *out, const u8 *in)
+static void aes_encrypt_sw(void *ctx_arg, u8 *out, const u8 *in)
 {
 	const struct aes_ctx *ctx = ctx_arg;
 	u32 b0[4], b1[4];
@@ -391,7 +447,7 @@ static void aes_encrypt(void *ctx_arg, u
     i_rl(bo, bi, 2, k);     \
     i_rl(bo, bi, 3, k)

-static void aes_decrypt(void *ctx_arg, u8 *out, const u8 *in)
+static void aes_decrypt_sw(void *ctx_arg, u8 *out, const u8 *in)
 {
 	const struct aes_ctx *ctx = ctx_arg;
 	u32 b0[4], b1[4];
@@ -430,6 +486,198 @@ static void aes_decrypt(void *ctx_arg, u
 	u32_out (out + 12, b0[3]);
 }

+#ifdef CONFIG_CRYPTO_AES_PADLOCK
+/*
+ * Support for VIA PadLock hardware crypto engine.
+ */
+
+/* Control word. */
+union cword {
+	u32 cword[4];
+	struct {
+		int rounds:4;
+		int algo:3;
+		int keygen:1;
+		int interm:1;
+		int encdec:1;
+		int ksize:2;
+	} b;
+};
+
+typedef void (xcrypt_t)(u8 *input, u8 *output, u8 *key, u8 *iv,
+			void *control_word, u32 count);
+
+/* Tells whether the ACE is capable to generate
+   the extended key for a given key_len. */
+static inline int padlock_hw_extkey_available(u8 key_len)
+{
+	/* TODO: We should check the actual CPU model/stepping
+	         as it's likely that the capability will be
+	         added in the next CPU revisions. */
+	if (key_len == 16)
+		return 1;
+	return 0;
+}
+
+static inline void padlock_xcrypt_ecb(u8 *input, u8 *output, u8 *key,
+				      u8 *iv, void *control_word, u32 count)
+{
+	asm volatile ("pushfl; popfl");		/* enforce key reload. */
+	asm volatile (".byte 0xf3,0x0f,0xa7,0xc8"	/* rep xcryptecb */
+		      : "=m"(*output), "+S"(input), "+D"(output)
+		      : "d"(control_word), "b"(key), "c"(count));
+}
+
+static inline void padlock_xcrypt_cbc(u8 *input, u8 *output, u8 *key,
+				      u8 *iv, void *control_word, u32 count)
+{
+	asm volatile ("pushfl; popfl");		/* enforce key reload. */
+	asm volatile (".byte 0xf3,0x0f,0xa7,0xd0"	/* rep xcryptcbc */
+		      : "=m"(*output), "+S"(input), "+D"(output)
+		      : "d"(control_word), "b"(key), "c"(count), "a"(iv));
+}
+
+static inline void padlock_xcrypt_cfb(u8 *input, u8 *output, u8 *key,
+				      u8 *iv, void *control_word, u32 count)
+{
+	asm volatile ("pushfl; popfl");		/* enforce key reload. */
+	asm volatile (".byte 0xf3,0x0f,0xa7,0xe0"	/* rep xcryptcfb */
+		      : "=m"(*output), "+S"(input), "+D"(output)
+		      : "d"(control_word), "b"(key), "c"(count), "a"(iv));
+}
+
+static inline void padlock_xcrypt_ofb(u8 *input, u8 *output, u8 *key,
+				      u8 *iv, void *control_word, u32 count)
+{
+	asm volatile ("pushfl; popfl");		/* enforce key reload. */
+	asm volatile (".byte 0xf3,0x0f,0xa7,0xe8"	/* rep xcryptofb */
+		      : "=m"(*output), "+S"(input), "+D"(output)
+		      : "d"(control_word), "b"(key), "c"(count), "a"(iv));
+}
+
+static void aes_padlock(void *ctx_arg, u8 *out_arg, const u8 *in_arg,
+			const u8 *iv_arg, size_t nbytes, int encdec,
+			xcrypt_t xcrypt_func)
+{
+	/* Don't blindly modify this structure - the items must
+	   fit on 16-Bytes boundaries! */
+	struct padlock_xcrypt_data {
+		u8 iv[AES_BLOCK_SIZE];		/* Initialization vector */
+		union cword cword;		/* Control word */
+	};
+
+	u8 *in, *out, *iv;
+	void *key;
+	void *index = NULL;
+	struct aes_ctx *ctx = ctx_arg;
+	char bigbuf[sizeof(struct padlock_xcrypt_data) + 16];
+	struct padlock_xcrypt_data *data;
+
+	/* Place 'data' at the first 16-Bytes aligned address in 'bigbuf'. */
+	if (((long)bigbuf) & 0x0F)
+		data = (void*)(bigbuf + 16 - ((long)bigbuf & 0x0F));
+	else
+		data = (void*)bigbuf;
+
+	if (((long)in_arg) & 0x0F) {
+		in = crypto_aligned_kmalloc(nbytes, GFP_KERNEL, 16, &index);
+		memcpy(in, in_arg, nbytes);
+	}
+	else
+		in = (u8*)in_arg;
+
+	if (((long)out_arg) & 0x0F) {
+		if (index)
+			out = in;	/* xcrypt can work "in place" */
+		else
+			out = crypto_aligned_kmalloc(nbytes, GFP_KERNEL, 16, &index);
+	}
+	else
+		out = out_arg;
+
+	/* Always make a local copy of IV - xcrypt may change it! */
+	iv = data->iv;
+	if (iv_arg)
+		memcpy(iv, iv_arg, AES_BLOCK_SIZE);
+
+	/* Prepare Control word. */
+	memset (&data->cword, 0, sizeof(union cword));
+	data->cword.b.encdec = !encdec;	/* in the rest of cryptoapi ENC=1/DEC=0 */
+	data->cword.b.rounds = 10 + (ctx->key_length - 16) / 4;
+	data->cword.b.ksize = (ctx->key_length - 16) / 8;
+
+	/* Is the hardware capable to generate the extended key? */
+	if (!padlock_hw_extkey_available(ctx->key_length))
+		data->cword.b.keygen = 1;
+
+	/* ctx->E starts with a plain key - if the hardware is capable
+	   to generate the extended key itself we must supply
+	   the plain key for both Encryption and Decryption. */
+	if (encdec == CRYPTO_DIR_ENCRYPT || data->cword.b.keygen == 0)
+		key = ctx->E;
+	else
+		key = ctx->D;
+
+	(xcrypt_func)(in, out, key, iv, &data->cword, nbytes/16);
+
+	/* Copy the 16-Byte aligned output to the caller's buffer. */
+	if (out != out_arg)
+		memcpy(out_arg, out, nbytes);
+
+	if (index)
+		kfree(index);
+}
+
+static void aes_padlock_ecb(void *ctx, u8 *dst, const u8 *src, const u8 *iv,
+			    size_t nbytes, int encdec, int inplace)
+{
+	aes_padlock(ctx, dst, src, NULL, nbytes, encdec,
+		    padlock_xcrypt_ecb);
+}
+
+static void aes_padlock_cbc(void *ctx, u8 *dst, const u8 *src, const u8 *iv,
+			    size_t nbytes, int encdec, int inplace)
+{
+	aes_padlock(ctx, dst, src, iv, nbytes, encdec,
+		    padlock_xcrypt_cbc);
+}
+
+static void aes_padlock_cfb(void *ctx, u8 *dst, const u8 *src, const u8 *iv,
+			    size_t nbytes, int encdec, int inplace)
+{
+	aes_padlock(ctx, dst, src, iv, nbytes, encdec,
+		    padlock_xcrypt_cfb);
+}
+
+static void aes_padlock_ofb(void *ctx, u8 *dst, const u8 *src, const u8 *iv,
+			    size_t nbytes, int encdec, int inplace)
+{
+	aes_padlock(ctx, dst, src, iv, nbytes, encdec,
+		    padlock_xcrypt_ofb);
+}
+#endif
+
+static void aes_encrypt(void *ctx_arg, u8 *out, const u8 *in)
+{
+#ifdef CONFIG_CRYPTO_AES_PADLOCK
+	if (use_padlock)
+		aes_padlock(ctx_arg, out, in, NULL, AES_BLOCK_SIZE,
+			    CRYPTO_DIR_ENCRYPT, padlock_xcrypt_ecb);
+	else
+#endif
+		aes_encrypt_sw(ctx_arg, out, in);
+}
+
+static void aes_decrypt(void *ctx_arg, u8 *out, const u8 *in)
+{
+#ifdef CONFIG_CRYPTO_AES_PADLOCK
+	if (use_padlock)
+		aes_padlock (ctx_arg, out, in, NULL, AES_BLOCK_SIZE,
+			     CRYPTO_DIR_DECRYPT, padlock_xcrypt_ecb);
+	else
+#endif
+		aes_decrypt_sw (ctx_arg, out, in);
+}

 static struct crypto_alg aes_alg = {
 	.cra_name		=	"aes",
@@ -449,8 +697,39 @@ static struct crypto_alg aes_alg = {
 	}
 };

+#ifdef CONFIG_CRYPTO_AES_PADLOCK
+static int disable_via_padlock = 0;
+MODULE_PARM(disable_via_padlock, "i");
+MODULE_PARM_DESC(disable_via_padlock,
+		 "Disable use of VIA PadLock crypto engine even if it was available.");
+static int disable_multiblock = 0;
+MODULE_PARM(disable_multiblock, "i");
+MODULE_PARM_DESC(disable_multiblock,
+		 "Disable encryption of whole multiblock buffers.");
+#endif
+
 static int __init aes_init(void)
 {
+#ifdef CONFIG_CRYPTO_AES_PADLOCK
+	if (!disable_via_padlock)
+		use_padlock = cpu_has_xstore_enabled;
+	if (use_padlock) {
+		if (!disable_multiblock) {
+			aes_alg.cra_u.cipher.cia_max_nbytes = (size_t)-1;
+			aes_alg.cra_u.cipher.cia_req_align  = 16;
+			aes_alg.cra_u.cipher.cia_ecb        = aes_padlock_ecb;
+			aes_alg.cra_u.cipher.cia_cbc        = aes_padlock_cbc;
+			aes_alg.cra_u.cipher.cia_cfb        = aes_padlock_cfb;
+			aes_alg.cra_u.cipher.cia_ofb        = aes_padlock_ofb;
+		}
+		printk(KERN_NOTICE PFX
+			"Using VIA PadLock ACE for AES algorithm%s.\n",
+			disable_multiblock ? "" : " (multiblock)");
+	} else if (cpu_has_xstore_enabled)
+		printk(KERN_NOTICE PFX "VIA PadLock ACE is available but not used.\n");
+	else
+		printk(KERN_NOTICE PFX "Using software AES.\n");
+#endif
 	gen_tabs();
 	return crypto_register_alg(&aes_alg);
 }
@@ -465,4 +744,3 @@ module_exit(aes_fini);

 MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
 MODULE_LICENSE("Dual BSD/GPL");
-


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Support for VIA PadLock crypto engine
  2004-05-10 14:40 [PATCH 2/2] Support for VIA PadLock crypto engine Michal Ludvig
@ 2004-05-10 15:55 ` James Morris
  2004-05-10 19:23   ` Michal Ludvig
                     ` (3 more replies)
  0 siblings, 4 replies; 24+ messages in thread
From: James Morris @ 2004-05-10 15:55 UTC (permalink / raw)
  To: Michal Ludvig; +Cc: Andrew Morton, David S. Miller, linux-kernel

On Mon, 10 May 2004, Michal Ludvig wrote:

> It adds two new config options in the Cryptography section and if
> these are selected, aes.ko is built with the support for PadLock ACE.
> It can always be disabled with 'disable_via_padlock=1' module option
> in this case, or if the PadLock is not found in the CPU, aes.ko
> reverts to the software encryption.

We really need a proper framework for this (i.e. per-arch hardware and asm
support), not just hacks to the software AES module.


- James
-- 
James Morris
<jmorris@redhat.com>



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Support for VIA PadLock crypto engine
  2004-05-10 15:55 ` James Morris
@ 2004-05-10 19:23   ` Michal Ludvig
  2004-05-11 16:56   ` [PATCH 1/2] " Michal Ludvig
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 24+ messages in thread
From: Michal Ludvig @ 2004-05-10 19:23 UTC (permalink / raw)
  To: James Morris; +Cc: Andrew Morton, David S. Miller, linux-kernel

On Mon, 10 May 2004, James Morris wrote:

> On Mon, 10 May 2004, Michal Ludvig wrote:
>
> > It adds two new config options in the Cryptography section and if
> > these are selected, aes.ko is built with the support for PadLock ACE.
> > It can always be disabled with 'disable_via_padlock=1' module option
> > in this case, or if the PadLock is not found in the CPU, aes.ko
> > reverts to the software encryption.
>
> We really need a proper framework for this (i.e. per-arch hardware and asm
> support), not just hacks to the software AES module.

Yes, I know the presented approach wasn't too generic.

How about doing it in a device-like model? There would be different
providers for e.g. AES encryption and the kernel would autoload one of
them depending on say modprobe.conf settings. This way we'd have AES
implemented in software in one module and the PadLock AES in another.
By default the software versions would be used, but the user could choose
the one specific for their hardware.
Comments?

And how about the first patch for crypto/cipher.c? It extends the
interface for not only encryption/decryption of one block for given
algorithms, but also provides a way to do the transform of the whole
buffer in a given mode (ECB, CBC, ...). Is this acceptable in this form?
Should I do something similar for hash and compress functions to stay
consistent?

Michal Ludvig
-- 
* A mouse is a device used to point at the xterm you want to type in.
* Personal homepage - http://www.logix.cz/michal

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH 1/2] Support for VIA PadLock crypto engine
  2004-05-10 15:55 ` James Morris
  2004-05-10 19:23   ` Michal Ludvig
@ 2004-05-11 16:56   ` Michal Ludvig
  2004-05-12  8:55     ` Michal Ludvig
  2004-05-11 16:56   ` [PATCH 2/2] " Michal Ludvig
  2004-05-11 17:04   ` [PATCH 3/2 :-] " Michal Ludvig
  3 siblings, 1 reply; 24+ messages in thread
From: Michal Ludvig @ 2004-05-11 16:56 UTC (permalink / raw)
  To: James Morris; +Cc: Andrew Morton, David S. Miller, linux-kernel

On Mon, 10 May 2004, James Morris wrote:

> We really need a proper framework for this (i.e. per-arch hardware and asm
> support), not just hacks to the software AES module.

OK, I did it cleaner now :-)

First of all I splitted PadLock completely out of crypto/aes.c. Now it
lives in crypto/devices/padlock*.[ch] and can be configured in the
submenu "Crypto options"->"Hardware crypto devices". The compiled
module is called padlock.ko.

I added a new field into "struct crypto_alg" called "cra_preference".
This is set to CRYPTO_PREF_HARDWARE(=1) in the PadLock driver,
normally is equal to CRYPTO_PREF_SOFTWARE(=0). This field is used in
crypto/api.c:crypto_alg_lookup() where the alg entry with the highest
preference is returned. I.e. if both aes.ko and padlock.ko are loaded
(or compiled in), the AES from PadLock is used.

This way you can add new hardware drivers to crypto/devices/, all
of them can support many algorithms (not only ciphers, but also
digests and compression).

It is also possible to autoload padlock.ko whenever AES algo is
requested by adding "alias aes padlock" into /etc/modprobe.conf.

Do you like it better? :-)

BTW Attached is the modified generic patch, in the next mail will
follow the padlock-specific patch.

Michal Ludvig

diff -X exclude.txt -rupN linux-2.6.5.patched/crypto/api.c linux-2.6.5/crypto/api.c
--- linux-2.6.5.patched/crypto/api.c	2004-04-29 10:33:05.000000000 +0200
+++ linux-2.6.5/crypto/api.c	2004-05-11 14:42:55.000000000 +0200
@@ -43,14 +43,16 @@ struct crypto_alg *crypto_alg_lookup(con
 	down_read(&crypto_alg_sem);

 	list_for_each_entry(q, &crypto_alg_list, cra_list) {
-		if (!(strcmp(q->cra_name, name))) {
-			if (crypto_alg_get(q))
-				alg = q;
-			break;
-		}
+		if (!(strcmp(q->cra_name, name))
+		    && (!alg || alg->cra_preference < q->cra_preference))
+			alg = q;
 	}

+	if (! crypto_alg_get(alg))
+		alg = NULL;
+
 	up_read(&crypto_alg_sem);
+
 	return alg;
 }

@@ -163,20 +165,11 @@ void crypto_free_tfm(struct crypto_tfm *
 int crypto_register_alg(struct crypto_alg *alg)
 {
 	int ret = 0;
-	struct crypto_alg *q;

 	down_write(&crypto_alg_sem);
-
-	list_for_each_entry(q, &crypto_alg_list, cra_list) {
-		if (!(strcmp(q->cra_name, alg->cra_name))) {
-			ret = -EEXIST;
-			goto out;
-		}
-	}
-
 	list_add_tail(&alg->cra_list, &crypto_alg_list);
-out:
 	up_write(&crypto_alg_sem);
+
 	return ret;
 }

@@ -213,6 +206,19 @@ int crypto_alg_available(const char *nam
 	return ret;
 }

+void *crypto_aligned_kmalloc(size_t size, int mode, size_t alignment, void **index)
+{
+	char *ptr;
+
+	ptr = kmalloc(size + alignment, mode);
+	*index = ptr;
+	if (alignment > 1 && ((long)ptr & (alignment - 1))) {
+		ptr += alignment - ((long)ptr & (alignment - 1));
+	}
+
+	return ptr;
+}
+
 static int __init init_crypto(void)
 {
 	printk(KERN_INFO "Initializing Cryptographic API\n");
@@ -227,3 +233,4 @@ EXPORT_SYMBOL_GPL(crypto_unregister_alg)
 EXPORT_SYMBOL_GPL(crypto_alloc_tfm);
 EXPORT_SYMBOL_GPL(crypto_free_tfm);
 EXPORT_SYMBOL_GPL(crypto_alg_available);
+EXPORT_SYMBOL_GPL(crypto_aligned_kmalloc);
diff -X exclude.txt -rupN linux-2.6.5.patched/crypto/cipher.c linux-2.6.5/crypto/cipher.c
--- linux-2.6.5.patched/crypto/cipher.c	2004-04-29 10:33:05.000000000 +0200
+++ linux-2.6.5/crypto/cipher.c	2004-05-10 15:21:56.000000000 +0200
@@ -20,7 +20,31 @@
 #include "internal.h"
 #include "scatterwalk.h"

+#define CRA_CIPHER(tfm)	(tfm)->__crt_alg->cra_cipher
+
+#define DEF_TFM_FUNCTION(name,mode,encdec,iv)	\
+static int name(struct crypto_tfm *tfm,		\
+                struct scatterlist *dst,	\
+                struct scatterlist *src,	\
+		unsigned int nbytes)		\
+{						\
+	return crypt(tfm, dst, src, nbytes,	\
+		     mode, encdec, iv);		\
+}
+
+#define DEF_TFM_FUNCTION_IV(name,mode,encdec,iv)	\
+static int name(struct crypto_tfm *tfm,		\
+                struct scatterlist *dst,	\
+                struct scatterlist *src,	\
+		unsigned int nbytes, u8 *iv)	\
+{						\
+	return crypt(tfm, dst, src, nbytes,	\
+		     mode, encdec, iv);		\
+}
+
 typedef void (cryptfn_t)(void *, u8 *, const u8 *);
+typedef void (cryptblkfn_t)(void *, u8 *, const u8 *, const u8 *,
+			    size_t, int, int);
 typedef void (procfn_t)(struct crypto_tfm *, u8 *,
                         u8*, cryptfn_t, int enc, void *, int);

@@ -38,6 +62,36 @@ static inline void xor_128(u8 *a, const
 	((u32 *)a)[3] ^= ((u32 *)b)[3];
 }

+static void cbc_process(struct crypto_tfm *tfm, u8 *dst, u8 *src,
+			cryptfn_t *fn, int enc, void *info, int in_place)
+{
+	u8 *iv = info;
+
+	/* Null encryption */
+	if (!iv)
+		return;
+
+	if (enc) {
+		tfm->crt_u.cipher.cit_xor_block(iv, src);
+		(*fn)(crypto_tfm_ctx(tfm), dst, iv);
+		memcpy(iv, dst, crypto_tfm_alg_blocksize(tfm));
+	} else {
+		u8 stack[in_place ? crypto_tfm_alg_blocksize(tfm) : 0];
+		u8 *buf = in_place ? stack : dst;
+
+		(*fn)(crypto_tfm_ctx(tfm), buf, src);
+		tfm->crt_u.cipher.cit_xor_block(buf, iv);
+		memcpy(iv, src, crypto_tfm_alg_blocksize(tfm));
+		if (buf != dst)
+			memcpy(dst, buf, crypto_tfm_alg_blocksize(tfm));
+	}
+}
+
+static void ecb_process(struct crypto_tfm *tfm, u8 *dst, u8 *src,
+			cryptfn_t fn, int enc, void *info, int in_place)
+{
+	(*fn)(crypto_tfm_ctx(tfm), dst, src);
+}

 /*
  * Generic encrypt/decrypt wrapper for ciphers, handles operations across
@@ -47,20 +101,92 @@ static inline void xor_128(u8 *a, const
 static int crypt(struct crypto_tfm *tfm,
 		 struct scatterlist *dst,
 		 struct scatterlist *src,
-                 unsigned int nbytes, cryptfn_t crfn,
-                 procfn_t prfn, int enc, void *info)
+		 unsigned int nbytes,
+		 int mode, int enc, void *info)
 {
+	cryptfn_t *cryptofn = NULL;
+	procfn_t *processfn = NULL;
+	cryptblkfn_t *cryptomultiblockfn = NULL;
+
 	struct scatter_walk walk_in, walk_out;
-	const unsigned int bsize = crypto_tfm_alg_blocksize(tfm);
-	u8 tmp_src[nbytes > src->length ? bsize : 0];
-	u8 tmp_dst[nbytes > dst->length ? bsize : 0];
+	size_t max_nbytes = crypto_tfm_alg_max_nbytes(tfm);
+	size_t bsize = crypto_tfm_alg_blocksize(tfm);
+	int req_align = crypto_tfm_alg_req_align(tfm);
+	int ret = 0;
+	void *index_src = NULL, *index_dst = NULL;
+	u8 *iv = info;
+	u8 *tmp_src, *tmp_dst;

 	if (!nbytes)
-		return 0;
+		return ret;

 	if (nbytes % bsize) {
 		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
+	}
+
+	switch (mode) {
+		case CRYPTO_TFM_MODE_ECB:
+			if (CRA_CIPHER(tfm).cia_ecb)
+				cryptomultiblockfn = CRA_CIPHER(tfm).cia_ecb;
+			else {
+				cryptofn = (enc == CRYPTO_DIR_ENCRYPT) ? CRA_CIPHER(tfm).cia_encrypt : CRA_CIPHER(tfm).cia_decrypt;
+				processfn = ecb_process;
+			}
+			break;
+
+		case CRYPTO_TFM_MODE_CBC:
+			if (CRA_CIPHER(tfm).cia_cbc)
+				cryptomultiblockfn = CRA_CIPHER(tfm).cia_cbc;
+			else {
+				cryptofn = (enc == CRYPTO_DIR_ENCRYPT) ? CRA_CIPHER(tfm).cia_encrypt : CRA_CIPHER(tfm).cia_decrypt;
+				processfn = cbc_process;
+			}
+			break;
+
+		/* Until we have the appropriate {ofb,cfb,ctr}_process() functions,
+		   the following cases will return -ENOSYS if there is no HW support
+		   for the mode. */
+		case CRYPTO_TFM_MODE_OFB:
+			if (CRA_CIPHER(tfm).cia_ofb)
+				cryptomultiblockfn = CRA_CIPHER(tfm).cia_ofb;
+			else
+				return -ENOSYS;
+			break;
+
+		case CRYPTO_TFM_MODE_CFB:
+			if (CRA_CIPHER(tfm).cia_cfb)
+				cryptomultiblockfn = CRA_CIPHER(tfm).cia_cfb;
+			else
+				return -ENOSYS;
+			break;
+
+		case CRYPTO_TFM_MODE_CTR:
+			if (CRA_CIPHER(tfm).cia_ctr)
+				cryptomultiblockfn = CRA_CIPHER(tfm).cia_ctr;
+			else
+				return -ENOSYS;
+			break;
+
+		default:
+			BUG();
+	}
+
+	if (cryptomultiblockfn)
+		bsize = (max_nbytes > nbytes) ? nbytes : max_nbytes;
+
+	/* Some hardware crypto engines may require a specific
+	   alignment of the buffers. We will align the buffers
+	   already here to avoid their reallocating later. */
+	tmp_src = crypto_aligned_kmalloc(bsize, GFP_KERNEL,
+					 req_align, &index_src);
+	tmp_dst = crypto_aligned_kmalloc(bsize, GFP_KERNEL,
+					 req_align, &index_dst);
+
+	if (!index_src || !index_dst) {
+		ret = -ENOMEM;
+		goto out;
 	}

 	scatterwalk_start(&walk_in, src);
@@ -71,16 +197,23 @@ static int crypt(struct crypto_tfm *tfm,

 		scatterwalk_map(&walk_in, 0);
 		scatterwalk_map(&walk_out, 1);
+
 		src_p = scatterwalk_whichbuf(&walk_in, bsize, tmp_src);
 		dst_p = scatterwalk_whichbuf(&walk_out, bsize, tmp_dst);

-		nbytes -= bsize;
-
 		scatterwalk_copychunks(src_p, &walk_in, bsize, 0);

-		prfn(tfm, dst_p, src_p, crfn, enc, info,
-		     scatterwalk_samebuf(&walk_in, &walk_out,
-					 src_p, dst_p));
+		nbytes -= bsize;
+
+		if (cryptomultiblockfn)
+			(*cryptomultiblockfn)(crypto_tfm_ctx(tfm),
+					   dst_p, src_p, iv, bsize, enc,
+					   scatterwalk_samebuf(&walk_in, &walk_out,
+							       src_p, dst_p));
+		else
+			(*processfn)(tfm, dst_p, src_p, cryptofn, enc, info,
+				  scatterwalk_samebuf(&walk_in, &walk_out,
+						      src_p, dst_p));

 		scatterwalk_done(&walk_in, 0, nbytes);

@@ -88,46 +221,23 @@ static int crypt(struct crypto_tfm *tfm,
 		scatterwalk_done(&walk_out, 1, nbytes);

 		if (!nbytes)
-			return 0;
+			goto out;

 		crypto_yield(tfm);
 	}
-}

-static void cbc_process(struct crypto_tfm *tfm, u8 *dst, u8 *src,
-			cryptfn_t fn, int enc, void *info, int in_place)
-{
-	u8 *iv = info;
-
-	/* Null encryption */
-	if (!iv)
-		return;
-
-	if (enc) {
-		tfm->crt_u.cipher.cit_xor_block(iv, src);
-		fn(crypto_tfm_ctx(tfm), dst, iv);
-		memcpy(iv, dst, crypto_tfm_alg_blocksize(tfm));
-	} else {
-		u8 stack[in_place ? crypto_tfm_alg_blocksize(tfm) : 0];
-		u8 *buf = in_place ? stack : dst;
+out:
+	if (index_src)
+		kfree(index_src);
+	if (index_dst)
+		kfree(index_dst);

-		fn(crypto_tfm_ctx(tfm), buf, src);
-		tfm->crt_u.cipher.cit_xor_block(buf, iv);
-		memcpy(iv, src, crypto_tfm_alg_blocksize(tfm));
-		if (buf != dst)
-			memcpy(dst, buf, crypto_tfm_alg_blocksize(tfm));
-	}
-}
-
-static void ecb_process(struct crypto_tfm *tfm, u8 *dst, u8 *src,
-			cryptfn_t fn, int enc, void *info, int in_place)
-{
-	fn(crypto_tfm_ctx(tfm), dst, src);
+	return ret;
 }

 static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
 {
-	struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher;
+	struct cipher_alg *cia = &CRA_CIPHER(tfm);

 	if (keylen < cia->cia_min_keysize || keylen > cia->cia_max_keysize) {
 		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
@@ -137,80 +247,28 @@ static int setkey(struct crypto_tfm *tfm
 		                       &tfm->crt_flags);
 }

-static int ecb_encrypt(struct crypto_tfm *tfm,
-		       struct scatterlist *dst,
-                       struct scatterlist *src, unsigned int nbytes)
-{
-	return crypt(tfm, dst, src, nbytes,
-	             tfm->__crt_alg->cra_cipher.cia_encrypt,
-	             ecb_process, 1, NULL);
-}
-
-static int ecb_decrypt(struct crypto_tfm *tfm,
-                       struct scatterlist *dst,
-                       struct scatterlist *src,
-		       unsigned int nbytes)
-{
-	return crypt(tfm, dst, src, nbytes,
-	             tfm->__crt_alg->cra_cipher.cia_decrypt,
-	             ecb_process, 1, NULL);
-}
-
-static int cbc_encrypt(struct crypto_tfm *tfm,
-                       struct scatterlist *dst,
-                       struct scatterlist *src,
-		       unsigned int nbytes)
-{
-	return crypt(tfm, dst, src, nbytes,
-	             tfm->__crt_alg->cra_cipher.cia_encrypt,
-	             cbc_process, 1, tfm->crt_cipher.cit_iv);
-}
-
-static int cbc_encrypt_iv(struct crypto_tfm *tfm,
-                          struct scatterlist *dst,
-                          struct scatterlist *src,
-                          unsigned int nbytes, u8 *iv)
-{
-	return crypt(tfm, dst, src, nbytes,
-	             tfm->__crt_alg->cra_cipher.cia_encrypt,
-	             cbc_process, 1, iv);
-}
+DEF_TFM_FUNCTION(ecb_encrypt, CRYPTO_TFM_MODE_ECB, CRYPTO_DIR_ENCRYPT, NULL);
+DEF_TFM_FUNCTION(ecb_decrypt, CRYPTO_TFM_MODE_ECB, CRYPTO_DIR_DECRYPT, NULL);

-static int cbc_decrypt(struct crypto_tfm *tfm,
-                       struct scatterlist *dst,
-                       struct scatterlist *src,
-		       unsigned int nbytes)
-{
-	return crypt(tfm, dst, src, nbytes,
-	             tfm->__crt_alg->cra_cipher.cia_decrypt,
-	             cbc_process, 0, tfm->crt_cipher.cit_iv);
-}
-
-static int cbc_decrypt_iv(struct crypto_tfm *tfm,
-                          struct scatterlist *dst,
-                          struct scatterlist *src,
-                          unsigned int nbytes, u8 *iv)
-{
-	return crypt(tfm, dst, src, nbytes,
-	             tfm->__crt_alg->cra_cipher.cia_decrypt,
-	             cbc_process, 0, iv);
-}
-
-static int nocrypt(struct crypto_tfm *tfm,
-                   struct scatterlist *dst,
-                   struct scatterlist *src,
-		   unsigned int nbytes)
-{
-	return -ENOSYS;
-}
-
-static int nocrypt_iv(struct crypto_tfm *tfm,
-                      struct scatterlist *dst,
-                      struct scatterlist *src,
-                      unsigned int nbytes, u8 *iv)
-{
-	return -ENOSYS;
-}
+DEF_TFM_FUNCTION(cbc_encrypt, CRYPTO_TFM_MODE_CBC, CRYPTO_DIR_ENCRYPT, tfm->crt_cipher.cit_iv);
+DEF_TFM_FUNCTION_IV(cbc_encrypt_iv, CRYPTO_TFM_MODE_CBC, CRYPTO_DIR_ENCRYPT, iv);
+DEF_TFM_FUNCTION(cbc_decrypt, CRYPTO_TFM_MODE_CBC, CRYPTO_DIR_DECRYPT, tfm->crt_cipher.cit_iv);
+DEF_TFM_FUNCTION_IV(cbc_decrypt_iv, CRYPTO_TFM_MODE_CBC, CRYPTO_DIR_DECRYPT, iv);
+
+DEF_TFM_FUNCTION(cfb_encrypt, CRYPTO_TFM_MODE_CFB, CRYPTO_DIR_ENCRYPT, tfm->crt_cipher.cit_iv);
+DEF_TFM_FUNCTION_IV(cfb_encrypt_iv, CRYPTO_TFM_MODE_CFB, CRYPTO_DIR_ENCRYPT, iv);
+DEF_TFM_FUNCTION(cfb_decrypt, CRYPTO_TFM_MODE_CFB, CRYPTO_DIR_DECRYPT, tfm->crt_cipher.cit_iv);
+DEF_TFM_FUNCTION_IV(cfb_decrypt_iv, CRYPTO_TFM_MODE_CFB, CRYPTO_DIR_DECRYPT, iv);
+
+DEF_TFM_FUNCTION(ofb_encrypt, CRYPTO_TFM_MODE_OFB, CRYPTO_DIR_ENCRYPT, tfm->crt_cipher.cit_iv);
+DEF_TFM_FUNCTION_IV(ofb_encrypt_iv, CRYPTO_TFM_MODE_OFB, CRYPTO_DIR_ENCRYPT, iv);
+DEF_TFM_FUNCTION(ofb_decrypt, CRYPTO_TFM_MODE_OFB, CRYPTO_DIR_DECRYPT, tfm->crt_cipher.cit_iv);
+DEF_TFM_FUNCTION_IV(ofb_decrypt_iv, CRYPTO_TFM_MODE_OFB, CRYPTO_DIR_DECRYPT, iv);
+
+DEF_TFM_FUNCTION(ctr_encrypt, CRYPTO_TFM_MODE_CTR, CRYPTO_DIR_ENCRYPT, tfm->crt_cipher.cit_iv);
+DEF_TFM_FUNCTION_IV(ctr_encrypt_iv, CRYPTO_TFM_MODE_CTR, CRYPTO_DIR_ENCRYPT, iv);
+DEF_TFM_FUNCTION(ctr_decrypt, CRYPTO_TFM_MODE_CTR, CRYPTO_DIR_DECRYPT, tfm->crt_cipher.cit_iv);
+DEF_TFM_FUNCTION_IV(ctr_decrypt_iv, CRYPTO_TFM_MODE_CTR, CRYPTO_DIR_DECRYPT, iv);

 int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags)
 {
@@ -244,17 +302,24 @@ int crypto_init_cipher_ops(struct crypto
 		break;

 	case CRYPTO_TFM_MODE_CFB:
-		ops->cit_encrypt = nocrypt;
-		ops->cit_decrypt = nocrypt;
-		ops->cit_encrypt_iv = nocrypt_iv;
-		ops->cit_decrypt_iv = nocrypt_iv;
+		ops->cit_encrypt = cfb_encrypt;
+		ops->cit_decrypt = cfb_decrypt;
+		ops->cit_encrypt_iv = cfb_encrypt_iv;
+		ops->cit_decrypt_iv = cfb_decrypt_iv;
+		break;
+
+	case CRYPTO_TFM_MODE_OFB:
+		ops->cit_encrypt = ofb_encrypt;
+		ops->cit_decrypt = ofb_decrypt;
+		ops->cit_encrypt_iv = ofb_encrypt_iv;
+		ops->cit_decrypt_iv = ofb_decrypt_iv;
 		break;

 	case CRYPTO_TFM_MODE_CTR:
-		ops->cit_encrypt = nocrypt;
-		ops->cit_decrypt = nocrypt;
-		ops->cit_encrypt_iv = nocrypt_iv;
-		ops->cit_decrypt_iv = nocrypt_iv;
+		ops->cit_encrypt = ctr_encrypt;
+		ops->cit_decrypt = ctr_decrypt;
+		ops->cit_encrypt_iv = ctr_encrypt_iv;
+		ops->cit_decrypt_iv = ctr_decrypt_iv;
 		break;

 	default:
diff -X exclude.txt -rup linux-2.6.5.patched/include/linux/crypto.h linux-2.6.5/include/linux/crypto.h
--- linux-2.6.5.patched/include/linux/crypto.h	2004-04-29 10:32:25.000000000 +0200
+++ linux-2.6.5/include/linux/crypto.h	2004-05-11 12:59:11.000000000 +0200
@@ -42,6 +42,7 @@
 #define CRYPTO_TFM_MODE_CBC		0x00000002
 #define CRYPTO_TFM_MODE_CFB		0x00000004
 #define CRYPTO_TFM_MODE_CTR		0x00000008
+#define CRYPTO_TFM_MODE_OFB		0x00000010

 #define CRYPTO_TFM_REQ_WEAK_KEY		0x00000100
 #define CRYPTO_TFM_RES_WEAK_KEY		0x00100000
@@ -56,6 +57,12 @@
 #define CRYPTO_UNSPEC			0
 #define CRYPTO_MAX_ALG_NAME		64

+#define CRYPTO_DIR_ENCRYPT		1
+#define CRYPTO_DIR_DECRYPT		0
+
+#define CRYPTO_PREF_SOFTWARE		0
+#define CRYPTO_PREF_HARDWARE		1
+
 struct scatterlist;

 /*
@@ -69,6 +76,18 @@ struct cipher_alg {
 	                  unsigned int keylen, u32 *flags);
 	void (*cia_encrypt)(void *ctx, u8 *dst, const u8 *src);
 	void (*cia_decrypt)(void *ctx, u8 *dst, const u8 *src);
+	size_t cia_max_nbytes;
+	size_t cia_req_align;
+	void (*cia_ecb)(void *ctx, u8 *dst, const u8 *src, const u8 *iv,
+			size_t nbytes, int encdec, int inplace);
+	void (*cia_cbc)(void *ctx, u8 *dst, const u8 *src, const u8 *iv,
+			size_t nbytes, int encdec, int inplace);
+	void (*cia_cfb)(void *ctx, u8 *dst, const u8 *src, const u8 *iv,
+			size_t nbytes, int encdec, int inplace);
+	void (*cia_ofb)(void *ctx, u8 *dst, const u8 *src, const u8 *iv,
+			size_t nbytes, int encdec, int inplace);
+	void (*cia_ctr)(void *ctx, u8 *dst, const u8 *src, const u8 *iv,
+			size_t nbytes, int encdec, int inplace);
 };

 struct digest_alg {
@@ -99,6 +118,7 @@ struct crypto_alg {
 	unsigned int cra_blocksize;
 	unsigned int cra_ctxsize;
 	const char cra_name[CRYPTO_MAX_ALG_NAME];
+	unsigned int cra_preference;

 	union {
 		struct cipher_alg cipher;
@@ -121,6 +141,11 @@ int crypto_unregister_alg(struct crypto_
 int crypto_alg_available(const char *name, u32 flags);

 /*
+ * Helper function.
+ */
+void *crypto_aligned_kmalloc (size_t size, int mode, size_t alignment, void **index);
+
+/*
  * Transforms: user-instantiated objects which encapsulate algorithms
  * and core processing logic.  Managed via crypto_alloc_tfm() and
  * crypto_free_tfm(), as well as the various helpers below.
@@ -255,6 +280,18 @@ static inline unsigned int crypto_tfm_al
 	return tfm->__crt_alg->cra_digest.dia_digestsize;
 }

+static inline unsigned int crypto_tfm_alg_max_nbytes(struct crypto_tfm *tfm)
+{
+	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+	return tfm->__crt_alg->cra_cipher.cia_max_nbytes;
+}
+
+static inline unsigned int crypto_tfm_alg_req_align(struct crypto_tfm *tfm)
+{
+	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+	return tfm->__crt_alg->cra_cipher.cia_req_align;
+}
+
 /*
  * API wrappers.
  */

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH 2/2] Support for VIA PadLock crypto engine
  2004-05-10 15:55 ` James Morris
  2004-05-10 19:23   ` Michal Ludvig
  2004-05-11 16:56   ` [PATCH 1/2] " Michal Ludvig
@ 2004-05-11 16:56   ` Michal Ludvig
  2004-05-12 13:37     ` James Morris
  2004-05-11 17:04   ` [PATCH 3/2 :-] " Michal Ludvig
  3 siblings, 1 reply; 24+ messages in thread
From: Michal Ludvig @ 2004-05-11 16:56 UTC (permalink / raw)
  To: James Morris; +Cc: Andrew Morton, David S. Miller, linux-kernel

Second patch - now the PadLock-specific part.

Michal Ludvig

diff -X exclude.txt -rupN linux-2.6.5.patched/crypto/Kconfig linux-2.6.5/crypto/Kconfig
--- linux-2.6.5.patched/crypto/Kconfig	2004-04-29 10:33:05.000000000 +0200
+++ linux-2.6.5/crypto/Kconfig	2004-05-11 08:34:32.000000000 +0200
@@ -176,5 +176,6 @@ config CRYPTO_TEST
 	help
 	  Quick & dirty crypto test module.

+source "crypto/devices/Kconfig"
 endmenu

diff -X exclude.txt -rupN linux-2.6.5.patched/crypto/Makefile linux-2.6.5/crypto/Makefile
--- linux-2.6.5.patched/crypto/Makefile	2004-04-29 10:33:05.000000000 +0200
+++ linux-2.6.5/crypto/Makefile	2004-05-11 08:34:49.000000000 +0200
@@ -26,3 +26,5 @@ obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.
 obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o

 obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
+
+obj-y += devices/
diff -X exclude.txt -rupN linux-2.6.5.patched/crypto/devices/Kconfig linux-2.6.5/crypto/devices/Kconfig
--- linux-2.6.5.patched/crypto/devices/Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.5/crypto/devices/Kconfig	2004-05-11 10:59:16.000000000 +0200
@@ -0,0 +1,23 @@
+menu "Hardware crypto devices"
+
+config CRYPTO_DEV_PADLOCK
+	tristate "Support for VIA PadLock ACE"
+	depends on CRYPTO && X86 && !X86_64
+	help
+	  Some VIA processors come with an integrated crypto engine
+	  (so called VIA PadLock ACE, Advanced Cryptography Engine)
+	  that provides instructions for very fast {en,de}cryption
+	  with some algorithms.
+
+	  The instructions are used only when the CPU supports them.
+	  Otherwise software encryption is used. If you are unsure,
+	  say Y.
+
+config CRYPTO_DEV_PADLOCK_AES
+	bool "Support for AES in VIA PadLock"
+	depends on CRYPTO_DEV_PADLOCK
+	default y
+	help
+	  Use VIA PadLock for AES algorithm.
+
+endmenu
diff -X exclude.txt -rupN linux-2.6.5.patched/crypto/devices/Makefile linux-2.6.5/crypto/devices/Makefile
--- linux-2.6.5.patched/crypto/devices/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.5/crypto/devices/Makefile	2004-05-11 10:59:33.000000000 +0200
@@ -0,0 +1,7 @@
+
+obj-$(CONFIG_CRYPTO_DEV_PADLOCK) += padlock.o
+
+padlock-objs-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o
+
+padlock-objs := padlock-generic.o $(padlock-objs-y)
+
diff -X exclude.txt -rupN linux-2.6.5.patched/crypto/devices/padlock-aes.c linux-2.6.5/crypto/devices/padlock-aes.c
--- linux-2.6.5.patched/crypto/devices/padlock-aes.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.5/crypto/devices/padlock-aes.c	2004-05-11 15:08:39.000000000 +0200
@@ -0,0 +1,493 @@
+/*
+ * Cryptographic API.
+ *
+ * Support for VIA PadLock hardware crypto engine.
+ *
+ * Linux developers:
+ *  Michal Ludvig <mludvig@suse.cz>
+ *
+ * Key expansion routine taken from crypto/aes.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * ---------------------------------------------------------------------------
+ * Copyright (c) 2002, Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK.
+ * All rights reserved.
+ *
+ * LICENSE TERMS
+ *
+ * The free distribution and use of this software in both source and binary
+ * form is allowed (with or without changes) provided that:
+ *
+ *   1. distributions of this source code include the above copyright
+ *      notice, this list of conditions and the following disclaimer;
+ *
+ *   2. distributions in binary form include the above copyright
+ *      notice, this list of conditions and the following disclaimer
+ *      in the documentation and/or other associated materials;
+ *
+ *   3. the copyright holder's name is not used to endorse products
+ *      built using this software without specific written permission.
+ *
+ * ALTERNATIVELY, provided that this notice is retained in full, this product
+ * may be distributed under the terms of the GNU General Public License (GPL),
+ * in which case the provisions of the GPL apply INSTEAD OF those given above.
+ *
+ * DISCLAIMER
+ *
+ * This software is provided 'as is' with no explicit or implied warranties
+ * in respect of its properties, including, but not limited to, correctness
+ * and/or fitness for purpose.
+ * ---------------------------------------------------------------------------
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/crypto.h>
+#include <asm/byteorder.h>
+#include "padlock.h"
+
+#define AES_MIN_KEY_SIZE	16	/* in u8 units */
+#define AES_MAX_KEY_SIZE	32	/* ditto */
+#define AES_BLOCK_SIZE		16	/* ditto */
+#define AES_EXTENDED_KEY_SIZE	64	/* in u32 units */
+#define AES_EXTENDED_KEY_SIZE_B	(AES_EXTENDED_KEY_SIZE * sizeof(u32))
+
+static inline int aes_hw_extkey_available (u8 key_len);
+
+static inline
+u32 generic_rotr32 (const u32 x, const unsigned bits)
+{
+	const unsigned n = bits % 32;
+	return (x >> n) | (x << (32 - n));
+}
+
+static inline
+u32 generic_rotl32 (const u32 x, const unsigned bits)
+{
+	const unsigned n = bits % 32;
+	return (x << n) | (x >> (32 - n));
+}
+
+#define rotl generic_rotl32
+#define rotr generic_rotr32
+
+/*
+ * #define byte(x, nr) ((unsigned char)((x) >> (nr*8)))
+ */
+inline static u8
+byte(const u32 x, const unsigned n)
+{
+	return x >> (n << 3);
+}
+
+#define u32_in(x) le32_to_cpu(*(const u32 *)(x))
+#define u32_out(to, from) (*(u32 *)(to) = cpu_to_le32(from))
+
+struct aes_ctx {
+	u32 e_data[AES_EXTENDED_KEY_SIZE+4];
+	u32 d_data[AES_EXTENDED_KEY_SIZE+4];
+	int key_length;
+	u32 *E;
+	u32 *D;
+};
+
+#define E_KEY ctx->E
+#define D_KEY ctx->D
+
+static u8 pow_tab[256];
+static u8 log_tab[256];
+static u8 sbx_tab[256];
+static u8 isb_tab[256];
+static u32 rco_tab[10];
+static u32 ft_tab[4][256];
+static u32 it_tab[4][256];
+
+static u32 fl_tab[4][256];
+static u32 il_tab[4][256];
+
+static inline u8
+f_mult (u8 a, u8 b)
+{
+	u8 aa = log_tab[a], cc = aa + log_tab[b];
+
+	return pow_tab[cc + (cc < aa ? 1 : 0)];
+}
+
+#define ff_mult(a,b)    (a && b ? f_mult(a, b) : 0)
+
+#define f_rn(bo, bi, n, k)					\
+    bo[n] =  ft_tab[0][byte(bi[n],0)] ^				\
+             ft_tab[1][byte(bi[(n + 1) & 3],1)] ^		\
+             ft_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
+             ft_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
+
+#define i_rn(bo, bi, n, k)					\
+    bo[n] =  it_tab[0][byte(bi[n],0)] ^				\
+             it_tab[1][byte(bi[(n + 3) & 3],1)] ^		\
+             it_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
+             it_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
+
+#define ls_box(x)				\
+    ( fl_tab[0][byte(x, 0)] ^			\
+      fl_tab[1][byte(x, 1)] ^			\
+      fl_tab[2][byte(x, 2)] ^			\
+      fl_tab[3][byte(x, 3)] )
+
+#define f_rl(bo, bi, n, k)					\
+    bo[n] =  fl_tab[0][byte(bi[n],0)] ^				\
+             fl_tab[1][byte(bi[(n + 1) & 3],1)] ^		\
+             fl_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
+             fl_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
+
+#define i_rl(bo, bi, n, k)					\
+    bo[n] =  il_tab[0][byte(bi[n],0)] ^				\
+             il_tab[1][byte(bi[(n + 3) & 3],1)] ^		\
+             il_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
+             il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
+
+static void
+gen_tabs (void)
+{
+	u32 i, t;
+	u8 p, q;
+
+	/* log and power tables for GF(2**8) finite field with
+	   0x011b as modular polynomial - the simplest prmitive
+	   root is 0x03, used here to generate the tables */
+
+	for (i = 0, p = 1; i < 256; ++i) {
+		pow_tab[i] = (u8) p;
+		log_tab[p] = (u8) i;
+
+		p ^= (p << 1) ^ (p & 0x80 ? 0x01b : 0);
+	}
+
+	log_tab[1] = 0;
+
+	for (i = 0, p = 1; i < 10; ++i) {
+		rco_tab[i] = p;
+
+		p = (p << 1) ^ (p & 0x80 ? 0x01b : 0);
+	}
+
+	for (i = 0; i < 256; ++i) {
+		p = (i ? pow_tab[255 - log_tab[i]] : 0);
+		q = ((p >> 7) | (p << 1)) ^ ((p >> 6) | (p << 2));
+		p ^= 0x63 ^ q ^ ((q >> 6) | (q << 2));
+		sbx_tab[i] = p;
+		isb_tab[p] = (u8) i;
+	}
+
+	for (i = 0; i < 256; ++i) {
+		p = sbx_tab[i];
+
+		t = p;
+		fl_tab[0][i] = t;
+		fl_tab[1][i] = rotl (t, 8);
+		fl_tab[2][i] = rotl (t, 16);
+		fl_tab[3][i] = rotl (t, 24);
+
+		t = ((u32) ff_mult (2, p)) |
+		    ((u32) p << 8) |
+		    ((u32) p << 16) | ((u32) ff_mult (3, p) << 24);
+
+		ft_tab[0][i] = t;
+		ft_tab[1][i] = rotl (t, 8);
+		ft_tab[2][i] = rotl (t, 16);
+		ft_tab[3][i] = rotl (t, 24);
+
+		p = isb_tab[i];
+
+		t = p;
+		il_tab[0][i] = t;
+		il_tab[1][i] = rotl (t, 8);
+		il_tab[2][i] = rotl (t, 16);
+		il_tab[3][i] = rotl (t, 24);
+
+		t = ((u32) ff_mult (14, p)) |
+		    ((u32) ff_mult (9, p) << 8) |
+		    ((u32) ff_mult (13, p) << 16) |
+		    ((u32) ff_mult (11, p) << 24);
+
+		it_tab[0][i] = t;
+		it_tab[1][i] = rotl (t, 8);
+		it_tab[2][i] = rotl (t, 16);
+		it_tab[3][i] = rotl (t, 24);
+	}
+}
+
+#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)
+
+#define imix_col(y,x)       \
+    u   = star_x(x);        \
+    v   = star_x(u);        \
+    w   = star_x(v);        \
+    t   = w ^ (x);          \
+   (y)  = u ^ v ^ w;        \
+   (y) ^= rotr(u ^ t,  8) ^ \
+          rotr(v ^ t, 16) ^ \
+          rotr(t,24)
+
+/* initialise the key schedule from the user supplied key */
+
+#define loop4(i)                                    \
+{   t = rotr(t,  8); t = ls_box(t) ^ rco_tab[i];    \
+    t ^= E_KEY[4 * i];     E_KEY[4 * i + 4] = t;    \
+    t ^= E_KEY[4 * i + 1]; E_KEY[4 * i + 5] = t;    \
+    t ^= E_KEY[4 * i + 2]; E_KEY[4 * i + 6] = t;    \
+    t ^= E_KEY[4 * i + 3]; E_KEY[4 * i + 7] = t;    \
+}
+
+#define loop6(i)                                    \
+{   t = rotr(t,  8); t = ls_box(t) ^ rco_tab[i];    \
+    t ^= E_KEY[6 * i];     E_KEY[6 * i + 6] = t;    \
+    t ^= E_KEY[6 * i + 1]; E_KEY[6 * i + 7] = t;    \
+    t ^= E_KEY[6 * i + 2]; E_KEY[6 * i + 8] = t;    \
+    t ^= E_KEY[6 * i + 3]; E_KEY[6 * i + 9] = t;    \
+    t ^= E_KEY[6 * i + 4]; E_KEY[6 * i + 10] = t;   \
+    t ^= E_KEY[6 * i + 5]; E_KEY[6 * i + 11] = t;   \
+}
+
+#define loop8(i)                                    \
+{   t = rotr(t,  8); ; t = ls_box(t) ^ rco_tab[i];  \
+    t ^= E_KEY[8 * i];     E_KEY[8 * i + 8] = t;    \
+    t ^= E_KEY[8 * i + 1]; E_KEY[8 * i + 9] = t;    \
+    t ^= E_KEY[8 * i + 2]; E_KEY[8 * i + 10] = t;   \
+    t ^= E_KEY[8 * i + 3]; E_KEY[8 * i + 11] = t;   \
+    t  = E_KEY[8 * i + 4] ^ ls_box(t);    \
+    E_KEY[8 * i + 12] = t;                \
+    t ^= E_KEY[8 * i + 5]; E_KEY[8 * i + 13] = t;   \
+    t ^= E_KEY[8 * i + 6]; E_KEY[8 * i + 14] = t;   \
+    t ^= E_KEY[8 * i + 7]; E_KEY[8 * i + 15] = t;   \
+}
+
+static int
+aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
+{
+	struct aes_ctx *ctx = ctx_arg;
+	u32 i, t, u, v, w;
+	u32 P[AES_EXTENDED_KEY_SIZE];
+	u32 rounds;
+
+	printk("%s() PadLock\n", __func__);
+	if (key_len != 16 && key_len != 24 && key_len != 32) {
+		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+		return -EINVAL;
+	}
+
+	ctx->key_length = key_len;
+
+	ctx->E = ctx->e_data;
+	ctx->D = ctx->d_data;
+
+	/* Ensure 16-Bytes alignmentation of keys for VIA PadLock. */
+	if ((int)(ctx->e_data) & 0x0F)
+		ctx->E += 4 - (((int)(ctx->e_data) & 0x0F) / sizeof (ctx->e_data[0]));
+
+	if ((int)(ctx->d_data) & 0x0F)
+		ctx->D += 4 - (((int)(ctx->d_data) & 0x0F) / sizeof (ctx->d_data[0]));
+
+	E_KEY[0] = u32_in (in_key);
+	E_KEY[1] = u32_in (in_key + 4);
+	E_KEY[2] = u32_in (in_key + 8);
+	E_KEY[3] = u32_in (in_key + 12);
+
+	/* Don't generate extended keys if the hardware can do it. */
+	if (aes_hw_extkey_available(key_len))
+		return 0;
+
+	switch (key_len) {
+	case 16:
+		t = E_KEY[3];
+		for (i = 0; i < 10; ++i)
+			loop4 (i);
+		break;
+
+	case 24:
+		E_KEY[4] = u32_in (in_key + 16);
+		t = E_KEY[5] = u32_in (in_key + 20);
+		for (i = 0; i < 8; ++i)
+			loop6 (i);
+		break;
+
+	case 32:
+		E_KEY[4] = u32_in (in_key + 16);
+		E_KEY[5] = u32_in (in_key + 20);
+		E_KEY[6] = u32_in (in_key + 24);
+		t = E_KEY[7] = u32_in (in_key + 28);
+		for (i = 0; i < 7; ++i)
+			loop8 (i);
+		break;
+	}
+
+	D_KEY[0] = E_KEY[0];
+	D_KEY[1] = E_KEY[1];
+	D_KEY[2] = E_KEY[2];
+	D_KEY[3] = E_KEY[3];
+
+	for (i = 4; i < key_len + 24; ++i) {
+		imix_col (D_KEY[i], E_KEY[i]);
+	}
+
+	/* PadLock needs a different format of the decryption key. */
+	rounds = 10 + (key_len - 16) / 4;
+
+	for (i = 0; i < rounds; i++) {
+		P[((i + 1) * 4) + 0] = D_KEY[((rounds - i - 1) * 4) + 0];
+		P[((i + 1) * 4) + 1] = D_KEY[((rounds - i - 1) * 4) + 1];
+		P[((i + 1) * 4) + 2] = D_KEY[((rounds - i - 1) * 4) + 2];
+		P[((i + 1) * 4) + 3] = D_KEY[((rounds - i - 1) * 4) + 3];
+	}
+
+	P[0] = E_KEY[(rounds * 4) + 0];
+	P[1] = E_KEY[(rounds * 4) + 1];
+	P[2] = E_KEY[(rounds * 4) + 2];
+	P[3] = E_KEY[(rounds * 4) + 3];
+
+	memcpy(D_KEY, P, AES_EXTENDED_KEY_SIZE_B);
+
+	return 0;
+}
+
+/* Tells whether the ACE is capable to generate
+   the extended key for a given key_len. */
+static inline int aes_hw_extkey_available(u8 key_len)
+{
+	/* TODO: We should check the actual CPU model/stepping
+	         as it's likely that the capability will be
+	         added in the next CPU revisions. */
+	if (key_len == 16)
+		return 1;
+	return 0;
+}
+
+static void aes_padlock(void *ctx_arg, u8 *out_arg, const u8 *in_arg,
+			const u8 *iv_arg, size_t nbytes, int encdec,
+			int mode)
+{
+	struct aes_ctx *ctx = ctx_arg;
+	char bigbuf[sizeof(union cword) + 16];
+	union cword *cword;
+	void *key;
+
+	/* Place 'data' at the first 16-Bytes aligned address in 'bigbuf'. */
+	if (((long)bigbuf) & 0x0F)
+		cword = (void*)(bigbuf + 16 - ((long)bigbuf & 0x0F));
+	else
+		cword = (void*)bigbuf;
+
+	/* Prepare Control word. */
+	memset (cword, 0, sizeof(union cword));
+	cword->b.encdec = !encdec;	/* in the rest of cryptoapi ENC=1/DEC=0 */
+	cword->b.rounds = 10 + (ctx->key_length - 16) / 4;
+	cword->b.ksize = (ctx->key_length - 16) / 8;
+
+	/* Is the hardware capable to generate the extended key? */
+	if (!aes_hw_extkey_available(ctx->key_length))
+		cword->b.keygen = 1;
+
+	/* ctx->E starts with a plain key - if the hardware is capable
+	   to generate the extended key itself we must supply
+	   the plain key for both Encryption and Decryption. */
+	if (encdec == CRYPTO_DIR_ENCRYPT || cword->b.keygen == 0)
+		key = ctx->E;
+	else
+		key = ctx->D;
+
+	padlock_aligner(out_arg, in_arg, iv_arg, key, cword,
+			nbytes, AES_BLOCK_SIZE, encdec, mode);
+}
+
+static void aes_padlock_ecb(void *ctx, u8 *dst, const u8 *src, const u8 *iv,
+			    size_t nbytes, int encdec, int inplace)
+{
+	aes_padlock(ctx, dst, src, NULL, nbytes, encdec,
+		    CRYPTO_TFM_MODE_ECB);
+}
+
+static void aes_padlock_cbc(void *ctx, u8 *dst, const u8 *src, const u8 *iv,
+			    size_t nbytes, int encdec, int inplace)
+{
+	aes_padlock(ctx, dst, src, iv, nbytes, encdec,
+		    CRYPTO_TFM_MODE_CBC);
+}
+
+static void aes_padlock_cfb(void *ctx, u8 *dst, const u8 *src, const u8 *iv,
+			    size_t nbytes, int encdec, int inplace)
+{
+	aes_padlock(ctx, dst, src, iv, nbytes, encdec,
+		    CRYPTO_TFM_MODE_CFB);
+}
+
+static void aes_padlock_ofb(void *ctx, u8 *dst, const u8 *src, const u8 *iv,
+			    size_t nbytes, int encdec, int inplace)
+{
+	aes_padlock(ctx, dst, src, iv, nbytes, encdec,
+		    CRYPTO_TFM_MODE_OFB);
+}
+
+static void aes_encrypt(void *ctx_arg, u8 *out, const u8 *in)
+{
+	aes_padlock(ctx_arg, out, in, NULL, AES_BLOCK_SIZE,
+		    CRYPTO_DIR_ENCRYPT, CRYPTO_TFM_MODE_ECB);
+}
+
+static void aes_decrypt(void *ctx_arg, u8 *out, const u8 *in)
+{
+	aes_padlock (ctx_arg, out, in, NULL, AES_BLOCK_SIZE,
+		     CRYPTO_DIR_DECRYPT, CRYPTO_TFM_MODE_ECB);
+}
+
+static struct crypto_alg aes_alg = {
+	.cra_name		=	"aes",
+	.cra_preference		=	CRYPTO_PREF_HARDWARE,
+	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		=	AES_BLOCK_SIZE,
+	.cra_ctxsize		=	sizeof(struct aes_ctx),
+	.cra_module		=	THIS_MODULE,
+	.cra_list		=	LIST_HEAD_INIT(aes_alg.cra_list),
+	.cra_u			=	{
+		.cipher = {
+			.cia_min_keysize	=	AES_MIN_KEY_SIZE,
+			.cia_max_keysize	=	AES_MAX_KEY_SIZE,
+			.cia_setkey	   	= 	aes_set_key,
+			.cia_encrypt	 	=	aes_encrypt,
+			.cia_decrypt	  	=	aes_decrypt
+		}
+	}
+};
+
+static int disable_multiblock = 0;
+MODULE_PARM(disable_multiblock, "i");
+MODULE_PARM_DESC(disable_multiblock,
+		 "Disable encryption of whole multiblock buffers.");
+
+int __init padlock_init_aes(void)
+{
+	if (!disable_multiblock) {
+		aes_alg.cra_u.cipher.cia_max_nbytes = (size_t)-1;
+		aes_alg.cra_u.cipher.cia_req_align  = 16;
+		aes_alg.cra_u.cipher.cia_ecb        = aes_padlock_ecb;
+		aes_alg.cra_u.cipher.cia_cbc        = aes_padlock_cbc;
+		aes_alg.cra_u.cipher.cia_cfb        = aes_padlock_cfb;
+		aes_alg.cra_u.cipher.cia_ofb        = aes_padlock_ofb;
+	}
+
+	printk(KERN_NOTICE PFX
+		"Using VIA PadLock ACE for AES algorithm%s.\n",
+		disable_multiblock ? "" : " (multiblock)");
+
+	gen_tabs();
+	return crypto_register_alg(&aes_alg);
+}
+
+void __exit padlock_fini_aes(void)
+{
+	crypto_unregister_alg(&aes_alg);
+}
diff -X exclude.txt -rupN linux-2.6.5.patched/crypto/devices/padlock-generic.c linux-2.6.5/crypto/devices/padlock-generic.c
--- linux-2.6.5.patched/crypto/devices/padlock-generic.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.5/crypto/devices/padlock-generic.c	2004-05-11 11:05:10.000000000 +0200
@@ -0,0 +1,175 @@
+/*
+ * Cryptographic API.
+ *
+ * Support for VIA PadLock hardware crypto engine.
+ *
+ * Linux developers:
+ *  Michal Ludvig <mludvig@suse.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/crypto.h>
+#include <asm/byteorder.h>
+#include "padlock.h"
+
+#define PFX	"padlock: "
+
+typedef void (xcrypt_t)(u8 *input, u8 *output, u8 *key, u8 *iv,
+			void *control_word, u32 count);
+
+static inline void padlock_xcrypt_ecb(u8 *input, u8 *output, u8 *key,
+				      u8 *iv, void *control_word, u32 count)
+{
+	asm volatile ("pushfl; popfl");		/* enforce key reload. */
+	asm volatile (".byte 0xf3,0x0f,0xa7,0xc8"	/* rep xcryptecb */
+		      : "=m"(*output), "+S"(input), "+D"(output)
+		      : "d"(control_word), "b"(key), "c"(count));
+}
+
+static inline void padlock_xcrypt_cbc(u8 *input, u8 *output, u8 *key,
+				      u8 *iv, void *control_word, u32 count)
+{
+	asm volatile ("pushfl; popfl");		/* enforce key reload. */
+	asm volatile (".byte 0xf3,0x0f,0xa7,0xd0"	/* rep xcryptcbc */
+		      : "=m"(*output), "+S"(input), "+D"(output)
+		      : "d"(control_word), "b"(key), "c"(count), "a"(iv));
+}
+
+static inline void padlock_xcrypt_cfb(u8 *input, u8 *output, u8 *key,
+				      u8 *iv, void *control_word, u32 count)
+{
+	asm volatile ("pushfl; popfl");		/* enforce key reload. */
+	asm volatile (".byte 0xf3,0x0f,0xa7,0xe0"	/* rep xcryptcfb */
+		      : "=m"(*output), "+S"(input), "+D"(output)
+		      : "d"(control_word), "b"(key), "c"(count), "a"(iv));
+}
+
+static inline void padlock_xcrypt_ofb(u8 *input, u8 *output, u8 *key,
+				      u8 *iv, void *control_word, u32 count)
+{
+	asm volatile ("pushfl; popfl");		/* enforce key reload. */
+	asm volatile (".byte 0xf3,0x0f,0xa7,0xe8"	/* rep xcryptofb */
+		      : "=m"(*output), "+S"(input), "+D"(output)
+		      : "d"(control_word), "b"(key), "c"(count), "a"(iv));
+}
+
+void padlock_aligner(u8 *out_arg, const u8 *in_arg, const u8 *iv_arg,
+		     void *key, union cword *cword,
+		     size_t nbytes, size_t blocksize,
+		     int encdec, int mode)
+{
+	/* Don't blindly modify this structure - the items must
+	   fit on 16-Bytes boundaries! */
+	struct padlock_xcrypt_data {
+		u8 iv[blocksize];		/* Initialization vector */
+	};
+
+	u8 *in, *out, *iv;
+	void *index = NULL;
+	char bigbuf[sizeof(struct padlock_xcrypt_data) + 16];
+	struct padlock_xcrypt_data *data;
+
+	/* Place 'data' at the first 16-Bytes aligned address in 'bigbuf'. */
+	if (((long)bigbuf) & 0x0F)
+		data = (void*)(bigbuf + 16 - ((long)bigbuf & 0x0F));
+	else
+		data = (void*)bigbuf;
+
+	if (((long)in_arg) & 0x0F) {
+		in = crypto_aligned_kmalloc(nbytes, GFP_KERNEL, 16, &index);
+		memcpy(in, in_arg, nbytes);
+	}
+	else
+		in = (u8*)in_arg;
+
+	if (((long)out_arg) & 0x0F) {
+		if (index)
+			out = in;	/* xcrypt can work "in place" */
+		else
+			out = crypto_aligned_kmalloc(nbytes, GFP_KERNEL, 16, &index);
+	}
+	else
+		out = out_arg;
+
+	/* Always make a local copy of IV - xcrypt may change it! */
+	iv = data->iv;
+	if (iv_arg)
+		memcpy(iv, iv_arg, blocksize);
+
+	switch (mode) {
+		case CRYPTO_TFM_MODE_ECB:
+			padlock_xcrypt_ecb(in, out, key, iv, cword, nbytes/blocksize);
+			break;
+
+		case CRYPTO_TFM_MODE_CBC:
+			padlock_xcrypt_cbc(in, out, key, iv, cword, nbytes/blocksize);
+			break;
+
+		case CRYPTO_TFM_MODE_CFB:
+			padlock_xcrypt_cfb(in, out, key, iv, cword, nbytes/blocksize);
+			break;
+
+		case CRYPTO_TFM_MODE_OFB:
+			padlock_xcrypt_ofb(in, out, key, iv, cword, nbytes/blocksize);
+			break;
+
+		default:
+			BUG();
+	}
+
+	/* Copy the 16-Byte aligned output to the caller's buffer. */
+	if (out != out_arg)
+		memcpy(out_arg, out, nbytes);
+
+	if (index)
+		kfree(index);
+}
+
+static int __init padlock_init(void)
+{
+	int ret = -ENOSYS;
+
+	if (!cpu_has_xcrypt) {
+		printk(KERN_ERR PFX "VIA PadLock not detected.\n");
+		return -ENODEV;
+	}
+
+	if (!cpu_has_xcrypt_enabled) {
+		printk(KERN_ERR PFX "VIA PadLock detected, but not enabled. Hmm, strange...\n");
+		return -ENODEV;
+	}
+
+#ifdef CONFIG_CRYPTO_DEV_PADLOCK_AES
+	if ((ret = padlock_init_aes())) {
+		printk(KERN_ERR PFX "VIA PadLock AES initialization failed.\n");
+		return ret;
+	}
+#endif
+
+	if (ret == -ENOSYS)
+		printk(KERN_ERR PFX "Hmm, VIA PadLock was compiled without any algorithm.\n");
+
+	return ret;
+}
+
+static void __exit padlock_fini(void)
+{
+#ifdef CONFIG_CRYPTO_DEV_PADLOCK_AES
+	padlock_fini_aes();
+#endif
+}
+
+module_init(padlock_init);
+module_exit(padlock_fini);
+
+MODULE_DESCRIPTION("VIA PadLock crypto engine support.");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Michal Ludvig");
diff -X exclude.txt -rupN linux-2.6.5.patched/crypto/devices/padlock.h linux-2.6.5/crypto/devices/padlock.h
--- linux-2.6.5.patched/crypto/devices/padlock.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.5/crypto/devices/padlock.h	2004-05-11 15:46:59.885953752 +0200
@@ -0,0 +1,41 @@
+/*
+ * Cryptographic API.
+ *
+ * Copyright (c) 2004 Michal Ludvig <mludvig@suse.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#ifndef _CRYPTO_PADLOCK_H
+#define _CRYPTO_PADLOCK_H
+
+/* Control word. */
+union cword {
+	u32 cword[4];
+	struct {
+		int rounds:4;
+		int algo:3;
+		int keygen:1;
+		int interm:1;
+		int encdec:1;
+		int ksize:2;
+	} b;
+};
+
+#define PFX	"padlock: "
+
+void padlock_aligner(u8 *out_arg, const u8 *in_arg, const u8 *iv_arg,
+		     void *key, union cword *cword,
+		     size_t nbytes, size_t blocksize,
+		     int encdec, int mode);
+
+#ifdef CONFIG_CRYPTO_DEV_PADLOCK_AES
+int padlock_init_aes(void);
+void padlock_fini_aes(void);
+#endif
+
+#endif	/* _CRYPTO_PADLOCK_H */

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH 3/2 :-] Support for VIA PadLock crypto engine
  2004-05-10 15:55 ` James Morris
                     ` (2 preceding siblings ...)
  2004-05-11 16:56   ` [PATCH 2/2] " Michal Ludvig
@ 2004-05-11 17:04   ` Michal Ludvig
  3 siblings, 0 replies; 24+ messages in thread
From: Michal Ludvig @ 2004-05-11 17:04 UTC (permalink / raw)
  To: Andrew Morton; +Cc: David S. Miller, James Morris, linux-kernel

Ehm, one small patch was missing in the previous posting. Please apply
regardless on the rest. Thanks!

Michal Ludvig

diff -urp linux-2.6.5/include/asm-i386/cpufeature.h linux-2.6.5.patched/include/asm-i386/cpufeature.h
--- linux-2.6.5/include/asm-i386/cpufeature.h	2004-04-04 05:37:37.000000000 +0200
+++ linux-2.6.5.patched/include/asm-i386/cpufeature.h	2004-05-11 16:41:17.543714496 +0200
@@ -104,7 +104,9 @@
 #define cpu_has_cyrix_arr	boot_cpu_has(X86_FEATURE_CYRIX_ARR)
 #define cpu_has_centaur_mcr	boot_cpu_has(X86_FEATURE_CENTAUR_MCR)
 #define cpu_has_xstore		boot_cpu_has(X86_FEATURE_XSTORE)
+#define cpu_has_xstore_enabled	boot_cpu_has(X86_FEATURE_XSTORE_EN)
 #define cpu_has_xcrypt		boot_cpu_has(X86_FEATURE_XCRYPT)
+#define cpu_has_xcrypt_enabled	boot_cpu_has(X86_FEATURE_XCRYPT_EN)

 #endif /* __ASM_I386_CPUFEATURE_H */


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 1/2] Support for VIA PadLock crypto engine
  2004-05-11 16:56   ` [PATCH 1/2] " Michal Ludvig
@ 2004-05-12  8:55     ` Michal Ludvig
  0 siblings, 0 replies; 24+ messages in thread
From: Michal Ludvig @ 2004-05-12  8:55 UTC (permalink / raw)
  To: James Morris; +Cc: Andrew Morton, David S. Miller, linux-kernel

Anyone testing/comitting this, please also apply the following patch
on top of the previous ones.

Michal Ludvig

--- linux-2.6.5/crypto/api.c	2004-05-11 14:42:55.000000000 +0200
+++ linux-2.6.5/crypto/api.c	2004-05-12 10:40:15.217391920 +0200
@@ -48,7 +48,7 @@ struct crypto_alg *crypto_alg_lookup(con
 			alg = q;
 	}

-	if (! crypto_alg_get(alg))
+	if (alg && !crypto_alg_get(alg))
 		alg = NULL;

 	up_read(&crypto_alg_sem);

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Support for VIA PadLock crypto engine
  2004-05-11 16:56   ` [PATCH 2/2] " Michal Ludvig
@ 2004-05-12 13:37     ` James Morris
  2004-05-12 14:42       ` Michal Ludvig
  0 siblings, 1 reply; 24+ messages in thread
From: James Morris @ 2004-05-12 13:37 UTC (permalink / raw)
  To: Michal Ludvig; +Cc: Andrew Morton, David S. Miller, linux-kernel

On Tue, 11 May 2004, Michal Ludvig wrote:

> Second patch - now the PadLock-specific part.

Can you please just follow the model of arch/s390/crypto/ ?

This is arch-specific hardware, and should not need any changes to the
existing crypto API at this stage.


- James
-- 
James Morris
<jmorris@redhat.com>



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Support for VIA PadLock crypto engine
  2004-05-12 13:37     ` James Morris
@ 2004-05-12 14:42       ` Michal Ludvig
  2004-05-12 14:52         ` James Morris
  2004-05-13 12:59         ` [PATCH 2/2] Support for VIA PadLock crypto engine Jari Ruusu
  0 siblings, 2 replies; 24+ messages in thread
From: Michal Ludvig @ 2004-05-12 14:42 UTC (permalink / raw)
  To: James Morris; +Cc: Andrew Morton, David S. Miller, linux-kernel

On Wed, 12 May 2004, James Morris wrote:

> On Tue, 11 May 2004, Michal Ludvig wrote:
>
> > Second patch - now the PadLock-specific part.
>
> Can you please just follow the model of arch/s390/crypto/ ?
>
> This is arch-specific hardware, and should not need any changes to the
> existing crypto API at this stage.

I only briefly looked at the s390 crypto driver and it looks like it uses
a special /dev node along with some read/write/ioctl calls to do the
encryption. I.e. it doesn't seem to integrate with the CryptoAPI at all.
How could that be used for e.g. IPsec, cryptoloop, etc?

My padlock driver can be used for anything that uses CryptoAPI and in fact
it speeds things a lot (see a simple disk-based benchmark at
http://www.logix.cz/michal/dl/padlock.xp).

In fact I believe that the hardware-specific drivers (e.g. the S/390 one)
should be used in the cryptoapi as well and then the kernel should provide
a single, universal device with read/write/ioctl calls for all of them.
Not making a separete device for every piece of hardware on the market.
Am I wrong?

Michal Ludvig
-- 
* A mouse is a device used to point at the xterm you want to type in.
* Personal homepage - http://www.logix.cz/michal

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Support for VIA PadLock crypto engine
  2004-05-12 14:42       ` Michal Ludvig
@ 2004-05-12 14:52         ` James Morris
  2004-05-12 15:25           ` Michal Ludvig
  2004-05-13 12:59         ` [PATCH 2/2] Support for VIA PadLock crypto engine Jari Ruusu
  1 sibling, 1 reply; 24+ messages in thread
From: James Morris @ 2004-05-12 14:52 UTC (permalink / raw)
  To: Michal Ludvig; +Cc: Andrew Morton, David S. Miller, linux-kernel

On Wed, 12 May 2004, Michal Ludvig wrote:

> In fact I believe that the hardware-specific drivers (e.g. the S/390 one)
> should be used in the cryptoapi as well and then the kernel should provide
> a single, universal device with read/write/ioctl calls for all of them.
> Not making a separete device for every piece of hardware on the market.
> Am I wrong?

Providing a userspace API is an orthogonal issue, and really needs to be 
designed in conjunction with the async hardware API.

What I am suggesting is that you simply implement something like 
des_z990.c so that C3 users can load crypto alg modules which use their 
hardware.

- James
-- 
James Morris
<jmorris@redhat.com>



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Support for VIA PadLock crypto engine
  2004-05-12 14:52         ` James Morris
@ 2004-05-12 15:25           ` Michal Ludvig
  2004-05-13  0:44             ` James Morris
  0 siblings, 1 reply; 24+ messages in thread
From: Michal Ludvig @ 2004-05-12 15:25 UTC (permalink / raw)
  To: James Morris; +Cc: Andrew Morton, David S. Miller, linux-kernel

On Wed, 12 May 2004, James Morris wrote:

> On Wed, 12 May 2004, Michal Ludvig wrote:
>
> > In fact I believe that the hardware-specific drivers (e.g. the S/390 one)
> > should be used in the cryptoapi as well and then the kernel should provide
> > a single, universal device with read/write/ioctl calls for all of them.
> > Not making a separete device for every piece of hardware on the market.
> > Am I wrong?
>
> Providing a userspace API is an orthogonal issue, and really needs to be
> designed in conjunction with the async hardware API.
>
> What I am suggesting is that you simply implement something like
> des_z990.c so that C3 users can load crypto alg modules which use their
> hardware.

Sorry, I overlooked that one as I was using the 2.6.5 source.

If I'd do it the same way and only implement .cia_encrypt/.cia_decrypt
functions I wouldn't gain too much from the PadLock. The great thing is
that it can encrypt/decrypt the whole block of data (e.g. the whole disk
sector, 512B) at once using a selected mode (ECB, CBC, ...). With
.cia_encrypt/.cia_decrypt the block chaining is done in software and the
hardware is only called for encryption of a single block (e.g. 16B in case
of AES) at a time. This is a big overhead and throws away most of the
PadLock potential.

That's why I added .cia_ecb/.cia_cbc/... and modified cipher.c to call
these whole-block-at-once methods instead of doing
software-chaining+hardware-encryption. This way it's much much faster and
I don't think that the changes to the cipher.c are somehow unclean.

Or can I achieve the same without extending the API?

Michal Ludvig
-- 
* A mouse is a device used to point at the xterm you want to type in.
* Personal homepage - http://www.logix.cz/michal

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Support for VIA PadLock crypto engine
  2004-05-12 15:25           ` Michal Ludvig
@ 2004-05-13  0:44             ` James Morris
  2004-05-14 15:10               ` New list for CryptoAPI development Michal Ludvig
  0 siblings, 1 reply; 24+ messages in thread
From: James Morris @ 2004-05-13  0:44 UTC (permalink / raw)
  To: Michal Ludvig; +Cc: Andrew Morton, David S. Miller, linux-kernel

On Wed, 12 May 2004, Michal Ludvig wrote:

> That's why I added .cia_ecb/.cia_cbc/... and modified cipher.c to call
> these whole-block-at-once methods instead of doing
> software-chaining+hardware-encryption. This way it's much much faster and
> I don't think that the changes to the cipher.c are somehow unclean.
> 
> Or can I achieve the same without extending the API?

No, the current API would not support this.

These kind of features are a subset of general hardware support (rather
than simple arch specific extensions like the s390 stuff), which I think
we need to take into account before making changes to the API.

Perhaps we should set up a list specifically to discuss & implement the 
hardware crypto API, as there seem to be several disparate efforts going 
on.


- James
-- 
James Morris
<jmorris@redhat.com>





^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Support for VIA PadLock crypto engine
  2004-05-12 14:42       ` Michal Ludvig
  2004-05-12 14:52         ` James Morris
@ 2004-05-13 12:59         ` Jari Ruusu
  2004-05-13 18:30           ` Andrew Morton
  1 sibling, 1 reply; 24+ messages in thread
From: Jari Ruusu @ 2004-05-13 12:59 UTC (permalink / raw)
  To: Michal Ludvig; +Cc: James Morris, Andrew Morton, David S. Miller, linux-kernel

Michal Ludvig wrote:
> My padlock driver can be used for anything that uses CryptoAPI and in fact
> it speeds things a lot (see a simple disk-based benchmark at
> http://www.logix.cz/michal/dl/padlock.xp).

Cryptoapi version of AES is slowest implementation of AES that I know of.
For speed tests, please compare against more modern implementation.

Below is one old AES128 speed test that I ran on my 300 MHz test box:

KERNEL      IMPLEMENTATION  MODE                WRITE MiB/s     READ MiB/s
2.6.1       cryptoloop      single-key           5.21            4.08
2.6.1       loop-AES        single-key           9.52            7.56
2.6.1       loop-AES        multi-key(MD5 IV)    7.67            6.35
2.4.22aa1   loop-AES        single-key          10.55           10.16
2.4.22aa1   loop-AES        multi-key(MD5 IV)    8.75            8.13

The cryptoloop implementation is busted in more than one way, so it is
useless for security needs:

http://marc.theaimsgroup.com/?l=linux-kernel&m=107419912024246&w=2
http://marc.theaimsgroup.com/?l=linux-kernel&m=107719798631935&w=2

-- 
Jari Ruusu  1024R/3A220F51 5B 4B F9 BB D3 3F 52 E9  DB 1D EB E3 24 0E A9 DD

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Support for VIA PadLock crypto engine
  2004-05-13 12:59         ` [PATCH 2/2] Support for VIA PadLock crypto engine Jari Ruusu
@ 2004-05-13 18:30           ` Andrew Morton
  2004-05-13 19:02             ` Jari Ruusu
  0 siblings, 1 reply; 24+ messages in thread
From: Andrew Morton @ 2004-05-13 18:30 UTC (permalink / raw)
  To: Jari Ruusu; +Cc: michal, jmorris, davem, linux-kernel

Jari Ruusu <jariruusu@users.sourceforge.net> wrote:
>
>  The cryptoloop implementation is busted in more than one way, so it is
>  useless for security needs:

Is dm-crypt any better?

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Support for VIA PadLock crypto engine
  2004-05-13 18:30           ` Andrew Morton
@ 2004-05-13 19:02             ` Jari Ruusu
  2004-05-13 20:00               ` Michal Ludvig
  0 siblings, 1 reply; 24+ messages in thread
From: Jari Ruusu @ 2004-05-13 19:02 UTC (permalink / raw)
  To: Andrew Morton; +Cc: michal, jmorris, davem, linux-kernel

Andrew Morton wrote:
> Jari Ruusu <jariruusu@users.sourceforge.net> wrote:
> >  The cryptoloop implementation is busted in more than one way, so it is
> >  useless for security needs:
> 
> Is dm-crypt any better?

Nope. dm-crypt has same exploitable cryptographic flaws.

-- 
Jari Ruusu  1024R/3A220F51 5B 4B F9 BB D3 3F 52 E9  DB 1D EB E3 24 0E A9 DD

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Support for VIA PadLock crypto engine
  2004-05-13 19:02             ` Jari Ruusu
@ 2004-05-13 20:00               ` Michal Ludvig
  2004-05-14 13:31                 ` Jari Ruusu
  0 siblings, 1 reply; 24+ messages in thread
From: Michal Ludvig @ 2004-05-13 20:00 UTC (permalink / raw)
  To: Jari Ruusu; +Cc: Andrew Morton, jmorris, davem, linux-kernel

On Thu, 13 May 2004, Jari Ruusu wrote:

> Andrew Morton wrote:
> > Jari Ruusu <jariruusu@users.sourceforge.net> wrote:
> > >  The cryptoloop implementation is busted in more than one way, so it is
> > >  useless for security needs:
> >
> > Is dm-crypt any better?
>
> Nope. dm-crypt has same exploitable cryptographic flaws.

Could you be more descriptive?

Michal Ludvig
-- 
* A mouse is a device used to point at the xterm you want to type in.
* Personal homepage - http://www.logix.cz/michal

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Support for VIA PadLock crypto engine
  2004-05-13 20:00               ` Michal Ludvig
@ 2004-05-14 13:31                 ` Jari Ruusu
  2004-05-14 14:09                   ` Fruhwirth Clemens
  0 siblings, 1 reply; 24+ messages in thread
From: Jari Ruusu @ 2004-05-14 13:31 UTC (permalink / raw)
  To: Michal Ludvig; +Cc: Andrew Morton, jmorris, davem, linux-kernel

Michal Ludvig wrote:
> On Thu, 13 May 2004, Jari Ruusu wrote:
> > Andrew Morton wrote:
> > > Jari Ruusu <jariruusu@users.sourceforge.net> wrote:
> > > >  The cryptoloop implementation is busted in more than one way, so it is
> > > >  useless for security needs:
> > >
> > > Is dm-crypt any better?
> >
> > Nope. dm-crypt has same exploitable cryptographic flaws.
> 
> Could you be more descriptive?

cryptoloop and dm-crypt on-disk formats are FUBAR: precomputable ciphertexts
of known plaintext, and weak IV computation. Anything that claims
"cryptoloop compatible", and only that, is completely FUBAR. dm-crypt is
such. IOW, there are now _two_ backdoored device crypto implementations in
mainline.

Only remaining question is: How long are mainline guys going to continue to
scam people to using backdoored device crypto?

-- 
Jari Ruusu  1024R/3A220F51 5B 4B F9 BB D3 3F 52 E9  DB 1D EB E3 24 0E A9 DD

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Support for VIA PadLock crypto engine
  2004-05-14 13:31                 ` Jari Ruusu
@ 2004-05-14 14:09                   ` Fruhwirth Clemens
  2004-05-14 16:05                     ` Jari Ruusu
  0 siblings, 1 reply; 24+ messages in thread
From: Fruhwirth Clemens @ 2004-05-14 14:09 UTC (permalink / raw)
  To: Jari Ruusu; +Cc: Michal Ludvig, Andrew Morton, jmorris, davem, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1417 bytes --]

On Fri, May 14, 2004 at 04:31:20PM +0300, Jari Ruusu wrote:
> Michal Ludvig wrote:
> > On Thu, 13 May 2004, Jari Ruusu wrote:
> > > Andrew Morton wrote:
> > > > Jari Ruusu <jariruusu@users.sourceforge.net> wrote:
> > > > >  The cryptoloop implementation is busted in more than one way, so it is
> > > > >  useless for security needs:
> > > >
> > > > Is dm-crypt any better?
> > >
> > > Nope. dm-crypt has same exploitable cryptographic flaws.
> > 
> > Could you be more descriptive?
> 
> cryptoloop and dm-crypt on-disk formats are FUBAR: precomputable ciphertexts
> of known plaintext, and weak IV computation. Anything that claims
> "cryptoloop compatible", and only that, is completely FUBAR. dm-crypt is
> such. IOW, there are now _two_ backdoored device crypto implementations in
> mainline.

Jari, you're starting to annoy me. You have been campaigning with FUD
against cryptoloop/dm-crypt for too long now. There are NO exploitable
security holes in neither dm-crypt nor cryptoloop. There is room for
improving both IV deducation schemes, but it's a theoretic weakness, one
which should be corrected nonetheless. However, modern ciphers are designed
to resist known-plaintext attacks. The default setup of loop-aes' initrd is
a greater threat to security, but wait for my paper on this. In the
meantime, stop spreading FUD, especially stop abusing the term "backdoored"!

Clemens

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* New list for CryptoAPI development
  2004-05-13  0:44             ` James Morris
@ 2004-05-14 15:10               ` Michal Ludvig
  2004-05-17  8:39                 ` Arnd Bergmann
  0 siblings, 1 reply; 24+ messages in thread
From: Michal Ludvig @ 2004-05-14 15:10 UTC (permalink / raw)
  To: James Morris; +Cc: linux-kernel

On Wed, 12 May 2004, James Morris wrote:

> Perhaps we should set up a list specifically to discuss & implement the
> hardware crypto API, as there seem to be several disparate efforts going
> on.

OK, I created cryptoapi@lists.logix.cz mailing list.
It is mailman-driven, i.e. subscribe with an empty mail to
cryptoapi-subscribe@lists.logix.cz or through the web page
http://lists.logix.cz/mailman/listinfo/cryptoapi

All cryptography-in-the-kernel discussions are on-topic.

I hope to see you there ;-)

Michal Ludvig
-- 
* A mouse is a device used to point at the xterm you want to type in.
* Personal homepage - http://www.logix.cz/michal

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Support for VIA PadLock crypto engine
  2004-05-14 14:09                   ` Fruhwirth Clemens
@ 2004-05-14 16:05                     ` Jari Ruusu
  2004-05-16 15:32                       ` Fruhwirth Clemens
  0 siblings, 1 reply; 24+ messages in thread
From: Jari Ruusu @ 2004-05-14 16:05 UTC (permalink / raw)
  To: Fruhwirth Clemens
  Cc: Michal Ludvig, Andrew Morton, jmorris, davem, linux-kernel

Fruhwirth Clemens wrote:
> On Fri, May 14, 2004 at 04:31:20PM +0300, Jari Ruusu wrote:
> > cryptoloop and dm-crypt on-disk formats are FUBAR: precomputable ciphertexts
> > of known plaintext, and weak IV computation. Anything that claims
> > "cryptoloop compatible", and only that, is completely FUBAR. dm-crypt is
> > such. IOW, there are now _two_ backdoored device crypto implementations in
> > mainline.
> 
> Jari, you're starting to annoy me.

Hey, don't kill the messenger for bringing bad news.

loop-AES wasn't born perfect. But I have plead quilty for each and every
fuck-up that was there. And then went on and fixed the damn code.
Countermeasures against optimized dictionary attacks was included in 2001,
and stronger IV in 2003.

May I suggest that you do the same. Better late than never.

> You have been campaigning with FUD
> against cryptoloop/dm-crypt for too long now. There are NO exploitable
> security holes in neither dm-crypt nor cryptoloop.

In the past you, Fruhwirth, have demonstrated that you don't understand what
the security holes are. The fact that you still don't seem to undertand,
does not mean that the holes are not there.

> There is room for
> improving both IV deducation schemes, but it's a theoretic weakness, one
> which should be corrected nonetheless. However, modern ciphers are designed
> to resist known-plaintext attacks.

Optimized dictionary attack is exploitable. Ok, it requires major government
size funding, but what do you think NSA guys get paid for?

Watermark attack is exploitable using zero budget.

> The default setup of loop-aes' initrd is
> a greater threat to security, but wait for my paper on this.

I doubt it, but I'm waiting...

> In the meantime, stop spreading FUD,

You insisting that cryptoloop/dm-crypt do not have exploitable security
issues does not increase confidence at all. Quite the contrary, as it
implies that existing vulnerabilities won't be fixed.

>  especially stop abusing the term "backdoored"!

Initial crypto merge for mainline mount and losetup included support for
gpg-encrypted key files, and seeded+iterated key setup. This support was
merged to util-linux-2.12-WIP (work in progress). One cryptoloop developer
somehow managed to convince util-linux maintaner to drop those
countermeasures against optimized dictionary attacks. To protect the guilty,
I won't name his name here, but search linux-crypto archives for 14 Mar 2003
11:12:13 -0800 posting if you want know his name. Final util-linux-2.12 was
released with those countermeasures removed. In my opinion that was
deliberate implanting of exploitable vulnerability to mainline mount and
losetup. I call that backdoor. You call that whatever you want.

-- 
Jari Ruusu  1024R/3A220F51 5B 4B F9 BB D3 3F 52 E9  DB 1D EB E3 24 0E A9 DD

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Support for VIA PadLock crypto engine
  2004-05-14 16:05                     ` Jari Ruusu
@ 2004-05-16 15:32                       ` Fruhwirth Clemens
  2004-05-16 17:46                         ` Jari Ruusu
  0 siblings, 1 reply; 24+ messages in thread
From: Fruhwirth Clemens @ 2004-05-16 15:32 UTC (permalink / raw)
  To: Jari Ruusu; +Cc: Michal Ludvig, Andrew Morton, jmorris, davem, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 3214 bytes --]

On Fri, 2004-05-14 at 18:05, Jari Ruusu wrote:

> loop-AES wasn't born perfect. But I have plead quilty for each and every
> fuck-up that was there. And then went on and fixed the damn code.
> Countermeasures against optimized dictionary attacks was included in 2001,
> and stronger IV in 2003.

Your countermeasures to optimized dictionary attacks are suboptimal. The
following code is from your util-linux patch:

 aes_encrypt(&ctx, &loopinfo.lo_encrypt_key[ 0], &loopinfo.lo_encrypt_key[ 0]);
 aes_encrypt(&ctx, &loopinfo.lo_encrypt_key[16], &loopinfo.lo_encrypt_key[16]);
 /* exchange upper half of first block with lower half of second block */
 memcpy(&tempkey[0], &loopinfo.lo_encrypt_key[8], 8);
 memcpy(&loopinfo.lo_encrypt_key[8], &loopinfo.lo_encrypt_key[16], 8);
 memcpy(&loopinfo.lo_encrypt_key[16], &tempkey[0], 8);

Symmetric block ciphers can't be used as hashing per se. Neither seems the
swapping scheme you're using to be a standard hash construction for ciphers.
I suggest to read "Applied Cryptography", Bruce Schneier, "18.11 One-Way
hash functions using symmetric block algorithms" as an introduction to that
topic. To avoid this troubles all together, I recommend to use a standard
MAC instead.

Further, the iteration depth of 10^5 seems to be insufficient.

> > You have been campaigning with FUD
> > against cryptoloop/dm-crypt for too long now. There are NO exploitable
> > security holes in neither dm-crypt nor cryptoloop.
> 
> In the past you, Fruhwirth, have demonstrated that you don't understand what
> the security holes are. The fact that you still don't seem to undertand,
> does not mean that the holes are not there.

Everyone attending a rhetoric seminar learns, "If you run out of
arguments, attack the person itself". The attacks, you're speaking of in
the next paragraph, apply to the key deduction. That's very different
from IV deduction.

> Optimized dictionary attack is exploitable. Ok, it requires major government
> size funding, but what do you think NSA guys get paid for?
> 
> Watermark attack is exploitable using zero budget.

As I said, not cryptoloop's responsibility. 

> You insisting that cryptoloop/dm-crypt do not have exploitable security
> issues does not increase confidence at all. Quite the contrary, as it
> implies that existing vulnerabilities won't be fixed.

Please read my mails carefully. See the following paragraph:

> > There is room for improving both IV deducation schemes, but it's a
> > theoretic weakness, one which should be corrected nonetheless. 


> One cryptoloop developer
> somehow managed to convince util-linux maintaner to drop those
> countermeasures against optimized dictionary attacks. To protect the guilty,
> I won't name his name here, but search linux-crypto archives for 14 Mar 2003
> 11:12:13 -0800 posting if you want know his name. 

You are talking about util-linux again. Rusuu, don't try to fool the
audience by arguing for something totally different. Further if you try to
provide evidence for something, provide an URL to back your claims. I wasn't
able to find any mails in the archives dealing with that topic.

Best Regards, Clemens

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Support for VIA PadLock crypto engine
  2004-05-16 15:32                       ` Fruhwirth Clemens
@ 2004-05-16 17:46                         ` Jari Ruusu
  0 siblings, 0 replies; 24+ messages in thread
From: Jari Ruusu @ 2004-05-16 17:46 UTC (permalink / raw)
  To: Fruhwirth Clemens
  Cc: Michal Ludvig, Andrew Morton, jmorris, davem, linux-kernel

Fruhwirth Clemens wrote:
> Your countermeasures to optimized dictionary attacks are suboptimal. The
> following code is from your util-linux patch:
> 
>  aes_encrypt(&ctx, &loopinfo.lo_encrypt_key[ 0], &loopinfo.lo_encrypt_key[ 0]);
>  aes_encrypt(&ctx, &loopinfo.lo_encrypt_key[16], &loopinfo.lo_encrypt_key[16]);
>  /* exchange upper half of first block with lower half of second block */
>  memcpy(&tempkey[0], &loopinfo.lo_encrypt_key[8], 8);
>  memcpy(&loopinfo.lo_encrypt_key[8], &loopinfo.lo_encrypt_key[16], 8);
>  memcpy(&loopinfo.lo_encrypt_key[16], &tempkey[0], 8);
> 
> Symmetric block ciphers can't be used as hashing per se.

You nipped away part of code that does hashing.

> Neither seems the
> swapping scheme you're using to be a standard hash construction for ciphers.

Swapping upper half of first block with lower half of second block between
multiple iterations of encryption is correct way to extend block length.

> I suggest to read "Applied Cryptography", Bruce Schneier, "18.11 One-Way
> hash functions using symmetric block algorithms" as an introduction to that
> topic.

May I suggest that you read and understand the code before publishing
incorrect conclusions.

> To avoid this troubles all together, I recommend to use a standard
> MAC instead.

Recommended way of setting up encryption keys in loop-AES, is to use gpg
encrypted key file with random keys. gpg does all that salted+iterated key
setup without any user intervention. That quoted part of code is there for
backward compatibility.

> > > You have been campaigning with FUD
> > > against cryptoloop/dm-crypt for too long now. There are NO exploitable
> > > security holes in neither dm-crypt nor cryptoloop.
> >
> > In the past you, Fruhwirth, have demonstrated that you don't understand what
> > the security holes are. The fact that you still don't seem to undertand,
> > does not mean that the holes are not there.
> 
> Everyone attending a rhetoric seminar learns, "If you run out of
> arguments, attack the person itself". The attacks, you're speaking of in
> the next paragraph, apply to the key deduction. That's very different
> from IV deduction.

You said that I was spreading FUD. I said you are wrong. Fortunately
at least some of mainline kernel dudes seem to understand:

http://marc.theaimsgroup.com/?l=linux-kernel&m=107713612713381&w=2

> > Optimized dictionary attack is exploitable. Ok, it requires major government
> > size funding, but what do you think NSA guys get paid for?
> >
> > Watermark attack is exploitable using zero budget.
> 
> As I said, not cryptoloop's responsibility.

Optimized dictionary attack can be prevented using better mount and losetup
programs. Mainline util-linux is still backdoored.

Watermark attack is very much cryptoloop's and dm-crypt's responsibility.

> Please read my mails carefully. See the following paragraph:
> 
> > > There is room for improving both IV deducation schemes, but it's a
> > > theoretic weakness, one which should be corrected nonetheless.

As long as there are only promises, and unfixed exploitable vulnerabilities
remain in mainline cryptoloop+util-linux and dm-crypt+cryptsetup, people
continue to be scammed to using backdoored crypto.

> > One cryptoloop developer
> > somehow managed to convince util-linux maintaner to drop those
> > countermeasures against optimized dictionary attacks. To protect the guilty,
> > I won't name his name here, but search linux-crypto archives for 14 Mar 2003
> > 11:12:13 -0800 posting if you want know his name.
> 
> You are talking about util-linux again. Rusuu, don't try to fool the
> audience by arguing for something totally different. Further if you try to
> provide evidence for something, provide an URL to back your claims. I wasn't
> able to find any mails in the archives dealing with that topic.

Wrong list, sorry. It was CC'd to cryptoapi-devel:

http://www.kerneli.org/pipermail/cryptoapi-devel/2003-March/000506.html

-- 
Jari Ruusu  1024R/3A220F51 5B 4B F9 BB D3 3F 52 E9  DB 1D EB E3 24 0E A9 DD

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: New list for CryptoAPI development
  2004-05-14 15:10               ` New list for CryptoAPI development Michal Ludvig
@ 2004-05-17  8:39                 ` Arnd Bergmann
  2004-05-17  8:53                   ` Michal Ludvig
  0 siblings, 1 reply; 24+ messages in thread
From: Arnd Bergmann @ 2004-05-17  8:39 UTC (permalink / raw)
  To: Michal Ludvig; +Cc: James Morris, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 557 bytes --]

On Friday 14 May 2004 17:10, Michal Ludvig wrote:

> OK, I created cryptoapi@lists.logix.cz mailing list.
> It is mailman-driven, i.e. subscribe with an empty mail to
> cryptoapi-subscribe@lists.logix.cz or through the web page
> http://lists.logix.cz/mailman/listinfo/cryptoapi
> 
> All cryptography-in-the-kernel discussions are on-topic.
> 
> I hope to see you there ;-)

Sorry if I'm being ignorant here, but how is this supposed
to relate to the existing linux-crypto mailing list at
http://mail.nl.linux.org/linux-crypto/ ?

	Arnd <><

[-- Attachment #2: signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: New list for CryptoAPI development
  2004-05-17  8:39                 ` Arnd Bergmann
@ 2004-05-17  8:53                   ` Michal Ludvig
  0 siblings, 0 replies; 24+ messages in thread
From: Michal Ludvig @ 2004-05-17  8:53 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: linux-kernel, James Morris

On Mon, 17 May 2004, Arnd Bergmann wrote:

> On Friday 14 May 2004 17:10, Michal Ludvig wrote:
>
> > OK, I created cryptoapi@lists.logix.cz mailing list.
> > It is mailman-driven, i.e. subscribe with an empty mail to
> > cryptoapi-subscribe@lists.logix.cz or through the web page
> > http://lists.logix.cz/mailman/listinfo/cryptoapi
> >
> > All cryptography-in-the-kernel discussions are on-topic.
> >
> > I hope to see you there ;-)
>
> Sorry if I'm being ignorant here, but how is this supposed
> to relate to the existing linux-crypto mailing list at
> http://mail.nl.linux.org/linux-crypto/ ?

Simply - I didn't know about it ;-) When James Morris asked for a new
list I though there is not one already up. I only found cryptoapi-devel at
kerneli.org which seems to be closed already...

Michal Ludvig
-- 
* A mouse is a device used to point at the xterm you want to type in.
* Personal homepage - http://www.logix.cz/michal

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2004-05-17  8:53 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-05-10 14:40 [PATCH 2/2] Support for VIA PadLock crypto engine Michal Ludvig
2004-05-10 15:55 ` James Morris
2004-05-10 19:23   ` Michal Ludvig
2004-05-11 16:56   ` [PATCH 1/2] " Michal Ludvig
2004-05-12  8:55     ` Michal Ludvig
2004-05-11 16:56   ` [PATCH 2/2] " Michal Ludvig
2004-05-12 13:37     ` James Morris
2004-05-12 14:42       ` Michal Ludvig
2004-05-12 14:52         ` James Morris
2004-05-12 15:25           ` Michal Ludvig
2004-05-13  0:44             ` James Morris
2004-05-14 15:10               ` New list for CryptoAPI development Michal Ludvig
2004-05-17  8:39                 ` Arnd Bergmann
2004-05-17  8:53                   ` Michal Ludvig
2004-05-13 12:59         ` [PATCH 2/2] Support for VIA PadLock crypto engine Jari Ruusu
2004-05-13 18:30           ` Andrew Morton
2004-05-13 19:02             ` Jari Ruusu
2004-05-13 20:00               ` Michal Ludvig
2004-05-14 13:31                 ` Jari Ruusu
2004-05-14 14:09                   ` Fruhwirth Clemens
2004-05-14 16:05                     ` Jari Ruusu
2004-05-16 15:32                       ` Fruhwirth Clemens
2004-05-16 17:46                         ` Jari Ruusu
2004-05-11 17:04   ` [PATCH 3/2 :-] " Michal Ludvig

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).