Re: LRW implementation, please comment

2006-09-01 Thread rsnel
Hello,

On Fri, Sep 01, 2006 at 01:52:25PM +1000, Herbert Xu wrote:
> On Thu, Aug 31, 2006 at 02:39:30PM +0200, Rik Snel wrote:
> > This is an attempt at implementing LRW for the new blockcipher API.
> > Please review, test and comment. 
> 
> Thanks a lot for doing this.  It looks good to me.

That's good to hear.

> There are a few style (see Documentation/CodingStyle) issues.  It would
> be good if you can fix them up before I apply the patches.

Can you give some examples about what I missed from CodingStyle?
(I just reread it and I think my patch adheres pretty well to those
rules: tabs=8, K&R bracing, don't pollute global namespace etc...)

> Could you also convert the test vectors to use tcrypt.h/tcrypt.c?

Yes, I just didn't know what tcrypt.[ch] was for, otherwise I would have put
those vectors there in the first place. The last testvector, however,
won't fit because it is an entire 512 byte sector. (which is not that
bad, because alle narrow blocks (16 bytes) are encrypted independently,
no realistic testvector of a wide block cipher mode would fit. (ABL uses
blocks of any size, say 512 bytes, and if 1 bit changes in the plaintext
block, the whole cypher block will be affected) I will propose something
to fix that if ABL is finished.

Greetings,

Rik.

-- 
Nothing is ever a total loss; it can always serve as a bad example.
-
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv2 5/6] LRW, Liskov Rivest Wagner, a tweakable narrow block cipher mode

2006-09-01 Thread rsnel
From: Rik Snel <[EMAIL PROTECTED]>

Main module, this implements the Liskov Rivest Wagner block cipher mode
in the new blockcipher API. The implementation is based on ecb.c.

The LRW-32-AES specification I used can be found at:
http://grouper.ieee.org/groups/1619/email/pdf00017.pdf

It implements the optimization specified as optional in the
specification, and in addition it uses optimized multiplication
routines from gf128mul.c.

Since gf128mul.[ch] is not tested on bigendian, this cipher mode
may currently fail badly on bigendian machines.

Signed-off-by: Rik Snel <[EMAIL PROTECTED]>
---

Note: I rerolled the loop because it turned out that I had unrolled it
wrong. (I noticed it after I added the long testvector; a cypherblock
was split in two by a page boundary and the reconstructed block was
discarded because of an error in the unrolling).

 crypto/Kconfig  |   13 ++
 crypto/Makefile |1 
 crypto/lrw.c|  291 +++
 3 files changed, 305 insertions(+), 0 deletions(-)

diff --git a/crypto/Kconfig b/crypto/Kconfig
index 6b23c20..dfdfe08 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -156,6 +156,19 @@ config CRYPTO_CBC
  CBC: Cipher Block Chaining mode
  This block cipher algorithm is required for IPSec.
 
+config CRYPTO_LRW
+   tristate "LRW support (EXPERIMENTAL)"
+   depends on EXPERIMENTAL
+   select CRYPTO_BLKCIPHER
+   select CRYPTO_GF128MUL
+   default n
+   help
+ LRW: Liskov Rivest Wagner, a tweakable, non malleable, non movable
+ narrow block cipher mode. Use it with cipher specification string
+ aes-lrw-benbi, the key must be 256, 320 or 384. The first 128, 192
+ or 256 bits in the key are used for AES and the rest is used to tie
+ each cipher block to its logical position.
+
 config CRYPTO_DES
tristate "DES and Triple DES EDE cipher algorithms"
select CRYPTO_ALGAPI
diff --git a/crypto/Makefile b/crypto/Makefile
index bf0406b..e2e57be 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_CRYPTO_TGR192) += tgr192.o
 obj-$(CONFIG_CRYPTO_GF128MUL) += gf128mul.o
 obj-$(CONFIG_CRYPTO_ECB) += ecb.o
 obj-$(CONFIG_CRYPTO_CBC) += cbc.o
+obj-$(CONFIG_CRYPTO_LRW) += lrw.o
 obj-$(CONFIG_CRYPTO_DES) += des.o
 obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o
 obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o
diff --git a/crypto/lrw.c b/crypto/lrw.c
new file mode 100644
index 000..a037379
--- /dev/null
+++ b/crypto/lrw.c
@@ -0,0 +1,291 @@
+/* LRW: as defined by Cyril Guyot in
+ * http://grouper.ieee.org/groups/1619/email/pdf00017.pdf
+ *
+ * Copyright (c) 2006 Rik Snel <[EMAIL PROTECTED]>
+ *
+ * Based om ecb.c
+ * Copyright (c) 2006 Herbert Xu <[EMAIL PROTECTED]>
+ *
+ * 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.
+ */
+/* This implementation is checked against the test vectors in the above
+ * document and by a test vector provided by Ken Buchanan at
+ * http://www.mail-archive.com/stds-p1619@listserv.ieee.org/msg00173.html
+ *
+ * The test vectors are included in the testing module tcrypt.[ch] */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "b128ops.h"
+#include "gf128mul.h"
+
+struct priv {
+   struct crypto_cipher *child;
+   /* optimizes multiplying a random (non incrementing, as at the
+* start of a new sector) value with key2, we could also have
+* used 4k optimization tables or no optimization at all. In the
+* latter case we would have to store key2 here */
+   struct gf128mul_64k table;
+   /* stores:
+*  key2*{ 0,0,...0,0,0,0,1 }, key2*{ 0,0,...0,0,0,1,1 },
+*  key2*{ 0,0,...0,0,1,1,1 }, key2*{ 0,0,...0,1,1,1,1 }
+*  key2*{ 0,0,...1,1,1,1,1 }, etc
+* needed for optimized multiplication of incrementing values
+* with key2 */
+   u64 mulinc[128][GF128MUL_BYTES >> 3];
+};
+
+static inline void setbit128(void *b, int bit)
+{
+   int index = 15 - bit/8;
+   ((u8 *)b)[index] |= 1<<(bit%8);
+}
+
+static int setkey(struct crypto_tfm *parent, const u8 *key,
+unsigned int keylen)
+{
+   struct priv *ctx = crypto_tfm_ctx(parent);
+   struct crypto_cipher *child = ctx->child;
+   int err, i;
+   u64 tmp[2] = { 0, }, scratch[2];
+   int bsize = crypto_cipher_blocksize(child);
+
+   crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
+   crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) &
+  CRYPTO_TFM_REQ_MASK);
+   if ((err = crypto_cipher_setkey(child, key, keylen - bsize)))
+   return err;
+   crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
+

[PATCHv2 3/6] crypto: some common 128-bit block operations, nicely centralized

2006-09-01 Thread rsnel
From: Rik Snel <[EMAIL PROTECTED]>

128bit is a common blocksize in linux kernel cryptography, so it helps to
centralize some common operations. The data must be aligned at sizeof(int)
for decent performance.

The code, while mostly trivial, is based on a header file mode_hdr.h in
http://fp.gladman.plus.com/AES/modes.vc8.19-06-06.zip

The original copyright (and GPL statement) of the original author,
Dr Brian Gladman, is preserved.

Signed-off-by: Rik Snel <[EMAIL PROTECTED]>
---
 crypto/b128ops.h |   72 ++
 1 files changed, 72 insertions(+), 0 deletions(-)

diff --git a/crypto/b128ops.h b/crypto/b128ops.h
new file mode 100644
index 000..73d8a5f
--- /dev/null
+++ b/crypto/b128ops.h
@@ -0,0 +1,72 @@
+/* b128ops.h - common 128-bit block operations
+ *
+ * Copyright (c) 2003, Dr Brian Gladman, Worcester, UK.
+ * Copyright (c) 2006, Rik Snel <[EMAIL PROTECTED]>
+ *
+ * Based on Dr Brian Gladman's (GPL'd) work published at
+ * http://fp.gladman.plus.com/cryptography_technology/index.htm
+ * See the original copyright notice below.
+ *
+ * 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) 2003, Dr Brian Gladman, 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.
+ ---
+ Issue Date: 13/06/2006
+*/
+
+#ifndef _LINUX_B128OPS_H
+#define _LINUX_B128OPS_H
+
+#include 
+
+/* watch out: for good performance p and q must be aligned to 32bit
+ * boundaries on a 32bit machine and to 64bit boundaries on a 64bit
+ * machine. */
+inline void b128ops_mov(void *p, const void *q)
+{
+   ((u64 *)p)[0] = ((u64 *)q)[0];
+   ((u64 *)p)[1] = ((u64 *)q)[1];
+}
+
+inline void b128ops_xor(void *p, const void *q)
+{
+   ((u64 *)p)[0] ^= ((u64 *)q)[0];
+   ((u64 *)p)[1] ^= ((u64 *)q)[1];
+}
+
+inline void bswap64_block(void *d, const void *s, u32 n)
+{
+   while(n--) ((u64 *)d)[n] = __swab64(((u64 *)s)[n]);
+}
+
+#endif /* _LINUX_B128OPS_H */
-- 
1.4.1.1


-- 
VGER BF report: U 0.5
-
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv2 6/6] LRW testvectors in tcrypt.[ch]

2006-09-01 Thread rsnel
From: Rik Snel <[EMAIL PROTECTED]>

Do modprobe tcrypt mode=10 to check the included test vectors, they are
from: http://grouper.ieee.org/groups/1619/email/pdf00017.pdf and from
http://www.mail-archive.com/stds-p1619@listserv.ieee.org/msg00173.html.

To make the last test vector fit, I had to increase the buffer size of
input and result to 512 bytes.

Signed-off-by: Rik Snel <[EMAIL PROTECTED]>
---
 crypto/tcrypt.c |   12 +
 crypto/tcrypt.h |  513 +++
 2 files changed, 521 insertions(+), 4 deletions(-)

diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index 840ab8b..0fd14c3 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -906,6 +906,10 @@ static void do_test(void)
AES_CBC_ENC_TEST_VECTORS);
test_cipher("cbc(aes)", DECRYPT, aes_cbc_dec_tv_template,
AES_CBC_DEC_TEST_VECTORS);
+   test_cipher("lrw(aes)", ENCRYPT, aes_lrw_enc_tv_template,
+   AES_LRW_ENC_TEST_VECTORS);
+   test_cipher("lrw(aes)", DECRYPT, aes_lrw_dec_tv_template,
+   AES_LRW_DEC_TEST_VECTORS);
 
//CAST5
test_cipher("ecb(cast5)", ENCRYPT, cast5_enc_tv_template,
@@ -1052,6 +1056,10 @@ static void do_test(void)
AES_CBC_ENC_TEST_VECTORS);
test_cipher("cbc(aes)", DECRYPT, aes_cbc_dec_tv_template,
AES_CBC_DEC_TEST_VECTORS);
+   test_cipher("lrw(aes)", ENCRYPT, aes_lrw_enc_tv_template,
+   AES_LRW_ENC_TEST_VECTORS);
+   test_cipher("lrw(aes)", DECRYPT, aes_lrw_dec_tv_template,
+   AES_LRW_DEC_TEST_VECTORS);
break;
 
case 11:
@@ -1191,6 +1199,10 @@ static void do_test(void)
  aes_speed_template);
test_cipher_speed("cbc(aes)", DECRYPT, sec, NULL, 0,
  aes_speed_template);
+   test_cipher_speed("lrw(aes)", ENCRYPT, sec, NULL, 0,
+ aes_speed_template);
+   test_cipher_speed("lrw(aes)", DECRYPT, sec, NULL, 0,
+ aes_speed_template);
break;
 
case 201:
diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h
index a40c441..0b60152 100644
--- a/crypto/tcrypt.h
+++ b/crypto/tcrypt.h
@@ -39,15 +39,15 @@ struct hash_testvec {
 struct cipher_testvec {
char key[MAX_KEYLEN] __attribute__ ((__aligned__(4)));
char iv[MAX_IVLEN];
-   char input[48];
-   char result[48];
+   char input[512];
+   char result[512];
unsigned char tap[MAX_TAP];
int np;
unsigned char fail;
unsigned char wk; /* weak key flag */
unsigned char klen;
-   unsigned char ilen;
-   unsigned char rlen;
+   unsigned short ilen;
+   unsigned short rlen;
 };
 
 struct cipher_speed {
@@ -1831,6 +1831,8 @@ #define AES_ENC_TEST_VECTORS 3
 #define AES_DEC_TEST_VECTORS 3
 #define AES_CBC_ENC_TEST_VECTORS 2
 #define AES_CBC_DEC_TEST_VECTORS 2
+#define AES_LRW_ENC_TEST_VECTORS 8
+#define AES_LRW_DEC_TEST_VECTORS 8
 
 static struct cipher_testvec aes_enc_tv_template[] = {
{ /* From FIPS-197 */
@@ -1968,6 +1970,509 @@ static struct cipher_testvec aes_cbc_dec
},
 };
 
+static struct cipher_testvec aes_lrw_enc_tv_template[] = {
+   /* from http://grouper.ieee.org/groups/1619/email/pdf00017.pdf */
+   { /* LRW-32-AES 1 */
+   .key= { 0x45, 0x62, 0xac, 0x25, 0xf8, 0x28, 0x17, 0x6d,
+   0x4c, 0x26, 0x84, 0x14, 0xb5, 0x68, 0x01, 0x85,
+   0x25, 0x8e, 0x2a, 0x05, 0xe7, 0x3e, 0x9d, 0x03,
+   0xee, 0x5a, 0x83, 0x0c, 0xcc, 0x09, 0x4c, 0x87 },
+   .klen   = 32,
+   .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+   .input  = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+   0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+   .ilen   = 16,
+   .result = { 0xf1, 0xb2, 0x73, 0xcd, 0x65, 0xa3, 0xdf, 0x5f,
+   0xe9, 0x5d, 0x48, 0x92, 0x54, 0x63, 0x4e, 0xb8 },
+   .rlen   = 16,
+   }, { /* LRW-32-AES 2 */
+   .key= { 0x59, 0x70, 0x47, 0x14, 0xf5, 0x57, 0x47, 0x8c,
+   0xd7, 0x79, 0xe8, 0x0f, 0x54, 0x88, 0x79, 0x44,
+   0x0d, 0x48, 0xf0, 0xb7, 0xb1, 0x5a, 0x53, 0xea,
+   0x1c, 0xaa, 0x6b, 0x29, 0xc2, 0xca, 0xfb, 0xaf
+   },
+   .klen   = 32,
+   .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
+   .input  = { 0x30, 0x31, 0x

[PATCHv2 1/6] crypto: trivial comment improvements

2006-09-01 Thread rsnel
From: Rik Snel <[EMAIL PROTECTED]>

Just some minor comment nits.

- little-endian is better than low-endian
- and since it is called essiv everywere it should also be essiv
  in the comments (and not ess_iv)

Signed-off-by: Rik Snel <[EMAIL PROTECTED]>
---
 drivers/md/dm-crypt.c |8 
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 91d4081..06961f7 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -99,12 +99,12 @@ static kmem_cache_t *_crypt_io_pool;
 /*
  * Different IV generation algorithms:
  *
- * plain: the initial vector is the 32-bit low-endian version of the sector
+ * plain: the initial vector is the 32-bit little-endian version of the sector
  *number, padded with zeros if neccessary.
  *
- * ess_iv: "encrypted sector|salt initial vector", the sector number is
- * encrypted with the bulk cipher using a salt as key. The salt
- * should be derived from the bulk cipher's key via hashing.
+ * essiv: "encrypted sector|salt initial vector", the sector number is
+ *encrypted with the bulk cipher using a salt as key. The salt
+ *should be derived from the bulk cipher's key via hashing.
  *
  * plumb: unimplemented, see:
  * http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/454
-- 
1.4.1.1


-- 
VGER BF report: U 0.496196
-
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv2 2/6] crypto: benbi IV, big endian narrow block count for LRW-32-AES

2006-09-01 Thread rsnel
From: Rik Snel <[EMAIL PROTECTED]>

LRW-32-AES needs a certain IV. This IV should be provided dm-crypt.
The block cipher mode could, in principle generate the correct IV from
the plain IV, but I think that it is cleaner to supply the right IV
directly.

The sector -> narrow block calculation uses a shift for performance reasons.
This shift is computed in .ctr and stored in cc->iv_gen_private (as a void*).

Signed-off-by: Rik Snel <[EMAIL PROTECTED]>
---
 drivers/md/dm-crypt.c |   56 -
 1 files changed, 55 insertions(+), 1 deletions(-)

diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 06961f7..df399d6 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -106,6 +106,9 @@ static kmem_cache_t *_crypt_io_pool;
  *encrypted with the bulk cipher using a salt as key. The salt
  *should be derived from the bulk cipher's key via hashing.
  *
+ * benbi: the 64-bit "big-endian 'narrow block'-count", starting at 1
+ *   (needed for LRW-32-AES and possible other narrow block modes)
+ *
  * plumb: unimplemented, see:
  * http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/454
  */
@@ -200,6 +203,49 @@ static int crypt_iv_essiv_gen(struct cry
return 0;
 }
 
+static int crypt_iv_benbi_ctr(struct crypt_config *cc, struct dm_target *ti,
+ const char *opts)
+{
+   unsigned int bs = crypto_blkcipher_blocksize(cc->tfm);
+   int log = long_log2(bs);
+
+   /* we need to calculate how far we must shift the sector count
+* to get the cipher block count, we use this shift in _gen */
+
+   if (1 << log != bs) {
+   ti->error = "cypher blocksize is not a power of 2";
+   return -EINVAL;
+   }
+
+   if (log > 9) {
+   ti->error = "cypher blocksize is > 512";
+   return -EINVAL;
+   }
+
+   if (crypto_blkcipher_ivsize(cc->tfm) < sizeof(u64)) {
+   ti->error = "cypher ivsize is < 8";
+   return -EINVAL;
+   }
+
+   cc->iv_gen_private = (void *)(9 - log);
+
+   return 0;
+}
+
+static void crypt_iv_benbi_dtr(struct crypt_config *cc)
+{
+   cc->iv_gen_private = NULL;
+}
+
+static int crypt_iv_benbi_gen(struct crypt_config *cc, u8 *iv, sector_t sector)
+{
+   memset(iv, 0, cc->iv_size - sizeof(u64)); /* rest is cleared below */
+   *(u64 *)(iv + cc->iv_size - sizeof(u64)) =
+   cpu_to_be64(((u64)sector << (u32)cc->iv_gen_private) + 1);
+
+   return 0;
+}
+
 static struct crypt_iv_operations crypt_iv_plain_ops = {
.generator = crypt_iv_plain_gen
 };
@@ -210,6 +256,11 @@ static struct crypt_iv_operations crypt_
.generator = crypt_iv_essiv_gen
 };
 
+static struct crypt_iv_operations crypt_iv_benbi_ops = {
+   .ctr   = crypt_iv_benbi_ctr,
+   .dtr   = crypt_iv_benbi_dtr,
+   .generator = crypt_iv_benbi_gen
+};
 
 static int
 crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out,
@@ -579,7 +630,8 @@ static int crypt_ctr(struct dm_target *t
cc->tfm = tfm;
 
/*
-* Choose ivmode. Valid modes: "plain", "essiv:".
+* Choose ivmode. Valid modes: "plain", "essiv:", "benbi".
+*
 * See comments at iv code
 */
 
@@ -589,6 +641,8 @@ static int crypt_ctr(struct dm_target *t
cc->iv_gen_ops = &crypt_iv_plain_ops;
else if (strcmp(ivmode, "essiv") == 0)
cc->iv_gen_ops = &crypt_iv_essiv_ops;
+   else if (strcmp(ivmode, "benbi") == 0)
+   cc->iv_gen_ops = &crypt_iv_benbi_ops;
else {
ti->error = "Invalid IV mode";
goto bad2;
-- 
1.4.1.1


-- 
VGER BF report: U 0.499935
-
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv2 4/6] crypto: table driven multiplications in GF(2^128), needed by LRW (and in the future ABL)

2006-09-01 Thread rsnel
From: Rik Snel <[EMAIL PROTECTED]>

WARNING: untested on bigendian, please test.

A lot of cypher modes need multiplications in GF(2^128). LRW, ABL, GCM...
I use functions from this library in my LRW implementation and I will
also use them in my ABL (Arbitrary Block Length, an unencumbered (correct
me if I am wrong, wide block cipher mode).

Elements of GF(2^128) must be presented as u64 * (specifically u64[2]),
it encourages automatic and proper alignment.

The library contains support for two different representations of GF(2^128),
see the comment in gf128mul.h. There different levels of optimization
(memory/speed tradeoff).

The code is based on work by Dr Brian Gladman. Notable changes:
- deletion of two optimization modes
- change from u32 to u64 for faster handling on 64bit machines
- support for 'bbe' representation in addition to the, already implemented,
  'lle' representation.
- move 'inline void' functions from header to 'static void' in the
  source file
- update to use the linux coding style conventions

The original can be found at:
http://fp.gladman.plus.com/AES/modes.vc8.19-06-06.zip

The copyright (and GPL statement) of the original author is preserved.

Signed-off-by: Rik Snel <[EMAIL PROTECTED]>
---
 crypto/Kconfig|   11 +
 crypto/Makefile   |1 
 crypto/gf128mul.c |  401 +
 crypto/gf128mul.h |  196 ++
 4 files changed, 609 insertions(+), 0 deletions(-)

diff --git a/crypto/Kconfig b/crypto/Kconfig
index 1e2f39c..6b23c20 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -128,6 +128,17 @@ config CRYPTO_TGR192
  See also:
  .
 
+config CRYPTO_GF128MUL
+   tristate "GF(2^128) multiplication functions (EXPERIMENTAL)"
+   depends on EXPERIMENTAL
+   default n
+   help
+ Efficient table driven implementation of multiplications in the
+ field GF(2^128). This is needed by some cypher modes. This
+ option will be selected automatically if you select such a
+ cipher mode. Only select this option by hand if you expect to load
+ an external module that requires these functions.
+
 config CRYPTO_ECB
tristate "ECB support"
select CRYPTO_BLKCIPHER
diff --git a/crypto/Makefile b/crypto/Makefile
index 7236620..bf0406b 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_CRYPTO_SHA256) += sha256.o
 obj-$(CONFIG_CRYPTO_SHA512) += sha512.o
 obj-$(CONFIG_CRYPTO_WP512) += wp512.o
 obj-$(CONFIG_CRYPTO_TGR192) += tgr192.o
+obj-$(CONFIG_CRYPTO_GF128MUL) += gf128mul.o
 obj-$(CONFIG_CRYPTO_ECB) += ecb.o
 obj-$(CONFIG_CRYPTO_CBC) += cbc.o
 obj-$(CONFIG_CRYPTO_DES) += des.o
diff --git a/crypto/gf128mul.c b/crypto/gf128mul.c
new file mode 100644
index 000..db92dc1
--- /dev/null
+++ b/crypto/gf128mul.c
@@ -0,0 +1,401 @@
+/* gf128mul.c - GF(2^128) multiplication functions
+ *
+ * Copyright (c) 2003, Dr Brian Gladman, Worcester, UK.
+ * Copyright (c) 2006, Rik Snel <[EMAIL PROTECTED]>
+ *
+ * Based on Dr Brian Gladman's (GPL'd) work published at
+ * http://fp.gladman.plus.com/cryptography_technology/index.htm
+ * See the original copyright notice below.
+ *
+ * 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) 2003, Dr Brian Gladman, 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.
+ ---
+ Issue 31/01/2006
+
+ This file provides fast multiplication in GF(128) as required by several
+ cryptographic authentication modes
+*/
+
+#include 
+#include "b128ops.h"
+#includ

Re: LRW... v2

2006-09-01 Thread rsnel

Hello Herbert/list,

Here is the updated version of my LRW patch set.

Greetings,

Rik.


-- 
VGER BF report: U 0.476584
-
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCHv2 4/6] crypto: table driven multiplications in GF(2^128), needed by LRW (and in the future ABL)

2006-11-28 Thread rsnel
Hello Herbert,

On Mon, Nov 27, 2006 at 10:56:07AM +1100, Herbert Xu wrote:
> On Sat, Sep 02, 2006 at 03:00:25AM +0200, [EMAIL PROTECTED] wrote:
>
> Sorry it took so long.  But I've been trying to modify the code so
> that the same source is used for both BE and LE machines.  I've
> finally accumulated enough time to finish it.

It's OK. The source will be more maintainable, but constantly converting
between big and little-endian (on little endian machines) may have a
significant performance impact (I will just test when your gf128 hits
cryptodev-2.6, and complain if it is the case).

Two more remarks (errors in v2 of my patch): b128ops.h and gf128mul.h
should be in include/ (so they can be used in modules) and the inline
functions in b128ops.h should also be static.

> Unfortunately it seems that the end result doesn't quite agree with
> your test vectors :) In particular, the LE version of your mul_x and
> mul_x8 functions don't agree with mine.
> 
> Could you please compare the two versions and double-check them?
> I'm unsure why 15 was used above as a shift count.  It would seem
> that 7 would seem to make more sense as endianness is byte-based
> not word-based.
> >
> > +#define M80X   0x8080808080808080LLU
> > +#define M01X   0x0101010101010101LLU
> > +
> > +static void gf128mul_x_lle(u64 r[2], const u64 x[2])
> > +{
> > +   u64  _tt = gf128mul_table_lle[(x[1] >> 49) & 0x80];
> > +   r[1] =  ((x[1] >> 1) & ~M80X) | (((x[1] << 15) | (x[0] >> 49)) & M80X);
> > +   r[0] = (((x[0] >> 1) & ~M80X) |  ((x[0] << 15) & M80X)) ^ _tt;
> > +}

I'll try to explain why I think the above code is correct:
As in my comment in gf128mul.h, lle means the polynomials in gf127 are
stored in little-little-endian format. So 
1000  ..  = 0x80 0x00 .. 0x00 = 1
0100  ..  = 0x40 0x00 .. 0x00 = X^1
01010001  .. 1000 = 0x51 0x00 .. 0x80 = X^1 + X^3 + X^7 + X^120
  .. 0001 = 0x00 0x00 .. 0x01 = X^127

The u64 type emulates a little endian 64bit processor (on my 32bit
intel) so when we load the these examples in two 64bit little endian
integers they are:
0x0080 0x = 1
0x0040 0x = X^1
0x0051 0x8000 = X^1 + X^3 + X^7 + X^120
0x 0x0100 = X^127

Let's multiply the third example by X, we should get
00101000 1000 .. 0100 = 0x28 0x80 .. 0x40 = X^2 + X^4 + X^8 + X^121

Represented as two little endian 64 bit values:
0x8028 0x4000

The above code implements this shift (efficiently?) by noting:
in each byte bit 1 moves to bit 0, bit 2 moves to bit 1, ..., bit 7
moves to bit 6 and all 7th bits are zeroed afterwards.
(this is done by ((x[1] >> 1) & ~M80X)), the 7th bits are set by moving
the least significant bits of the bytes to the right position (15 bits
to the left) and orring.

Let's look at the example: the first 8 in 0x0...008028 comes from the
least significant bit of 0x00.00051. So the shift by 15 to get the 7th
bit of every byte right is correct. (I have included a simple program
to compare the different implementations)

> I've attached my version of gf128mul which is based on your BE
> code.

Ok, will comment.

> The other main change I've made is to remove the need to
> allocate a contiguous 64K table in gf128mul.  Requiring every
> tfm to allocate a contiguous 64K chunk of memory is not realistic
> on Linux.

Ok.

> I also added a be128/le128/u128 type to make 128-bit operations
> easier.

I assume it is: typedef struct { u64 a, u64 b } be128; 
As long as compilers don't do u128 natively it is just a matter of taste.

> [...]
> +#define xx(p, q)   __constant_be16_to_cpu(0x##p##q)

This seems to be the problem, the table is constructed wrongly. 
All the calculations take place as if we are on a big endian machine, so
the table entries should never be swapped, so the above line should read

+#define xx(p, q)   0x##p##q

While investigating the problem, I wrote a small program to compare
a bytewise implementation with Brian's and your implementation of mul_x,
it only works in the lle implementation.

Once I found this problem, I stopped looking, so let me know if the test
vectors still don't match up, then I will need to take a closer look.

Greetings,

Rik.

/* test program for mutiplying by X in GF(2^128) in lle representation
 * on a little endian machine. */
/* GNU GPL >= v2 applies, (C) Brian Gladman, Herbert Xu, Rik Snel. */
#include 
#include 
#include 
#include 
#include 

typedef uint64_t u64;
typedef uint16_t u16;
typedef struct {
u64 a;
u64 b;
} be128;

#define gf128mul_dat(q) { \
q(0x00), q(0x01), q(0x02), q(0x03), q(0x04), q(0x05), q(0x06), q(0x07),\
q(0x08), q(0x09), q(0x0a), q(0x0b), q(0x0c), q(0x0d), q(0x0e), q(0x0f),\
q(0x10), q(0x11), q(0x12), q(0x13), q(0x14), q(0x15), q(0x16), q(0x17),\
q(0x18), q(0x19), q(0x1a), q(0x1b), q(0x1c), q(0x1d), q(0

Re: [PATCHv2 4/6] crypto: table driven multiplications in GF(2^128), needed by LRW (and in the future ABL)

2006-11-28 Thread rsnel
Hello Herbert,

On Wed, Nov 29, 2006 at 08:13:40AM +1100, Herbert Xu wrote:
> > It's OK. The source will be more maintainable, but constantly converting
> > between big and little-endian (on little endian machines) may have a
> > significant performance impact (I will just test when your gf128 hits
> > cryptodev-2.6, and complain if it is the case).
> 
> BTW, the tcrypt speed test for lrw doesn't work for me.

Did you try my patch: [PATCH] adding speed_test_template for lrw(aes)
which I sent on Sep 23?

> > This seems to be the problem, the table is constructed wrongly. 
> > All the calculations take place as if we are on a big endian machine, so
> > the table entries should never be swapped, so the above line should read
> > 
> > +#define xx(p, q)   0x##p##q
> 
> Yes you're quite right.  That was the problem.  I'll push this into mm
> as soon as I get the speed tests fixed.

Ok, that's good news.

Greetings,

Rik.

-- 
Nothing is ever a total loss; it can always serve as a bad example.
-
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


proposed XTS implementation

2007-09-03 Thread rsnel
Hello list (cc: Herbert, Christoph),

In my previous mail you will find a proposed patch to
implement XTS (a block cipher mode alike LRW, but unlike
LRW, no known security problems (LRW has problems encrypting
it's own key)). An email from Cristoph sparked my interest,
and the lrw.c file was a good starting point. You will find
that xts.c includes less weird functions than lrw.c.

xts.c is compilation tested as a module outside the kernel,
it 'hould work(tm).

Herbert: I need to instances of AES, did I do that correctly?

Greetings,

Rik.

-- 
Nothing is ever a total loss; it can always serve as a bad example.
-
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] an XTS blockcipher mode implementation without partial blocks

2007-09-06 Thread rsnel
Hello Sebastian,

Thanks for your review of the patch. I will address your points below.

On Wed, Sep 05, 2007 at 02:29:06AM +0200, Sebastian Siewior wrote:
> >diff --git a/crypto/xts.c b/crypto/xts.c
> [...]
> >+/* key consists of keys of equal size concatenated, therefore
> >+ * the length must be even */
> >+if (keylen % 2) {
> >+/* does anyone read this flag, it is not set if key setup
> >+ * fails below (or is it?) */
> >+*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
> >+return -EINVAL;
> >+}
> 
> A algo user might read this.

Ok. I see that the error flags from the keysetup below are also copied
to the flags..., will update comment.
> 
> >+
> >+/* we need two cipher instances: one to compute the inital 'tweak'
> >+ * by encrypting the IV (usually the 'plain' iv) and the other
> >+ * one to encrypt and decrypt the data */
> >+
> >+/* tweak cipher, uses Key2 i.e. the second half of *key */
> >+crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
> >+crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) &
> >+   CRYPTO_TFM_REQ_MASK);
> >+if ((err = crypto_cipher_setkey(child, key + keylen/2, keylen/2)))
> >+return err;
> 
> why not
>   err = crypto_cipher_setkey(child, key + keylen/2, keylen/2);
>   if (err)
>   return err;

Ok, I can see that it probably goes against the 'multiple statements on
a single line' rules in CodingStyle, will change.

> >+crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
> >+ CRYPTO_TFM_RES_MASK);
> >+
> >+child = ctx->child;
> >+
> >+/* data cipher, uses Key1 i.e. the first half of *key */
> >+crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
> >+crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) &
> >+   CRYPTO_TFM_REQ_MASK);
> >+if ((err = crypto_cipher_setkey(child, key, keylen/2)))
> ...

Copypaste from above...

> > [...]
> >+err = blkcipher_walk_virt(d, w);
> >+if (!(avail = w->nbytes))
> ...

Ok.

> >+return err;
> >+
> >+wsrc = w->src.virt.addr;
> >+wdst = w->dst.virt.addr;
> >+
> >+/* calculate first value of T */
> >+iv = (be128 *)w->iv;
> >+tw(crypto_cipher_tfm(ctx->tweak), (void*)&s.t, w->iv);
> >+
> >+goto first;
> >+
> >+for (;;) {
> >+do {
> >+gf128mul_x_ble(&s.t, &s.t);
> >+
> >+first:
> 
> why not
> 
> int first = 0;
> ...
> do {
>   if (!first) {
> gf128mul_x_ble(&s.t, &s.t);
> first = 1;
> }
> 
> The compiler should generate similar code.

I'd rather tell the compiler what I want than to introduce a new local
variable and a conditional branch in the hope that the compiler will
optimize it away, just to avoid a goto.

If you insist on getting rid of the goto, I could unroll the first
iteration of the loop by hand. (when is submitted lrw.c it had the first
iteration unrolled; Herbert replaced it with this goto)

> >+xts_round(&s, wdst, wsrc);
> >+
> >+wsrc += bs;
> >+wdst += bs;
> >+} while ((avail -= bs) >= bs);
> >+
> >+err = blkcipher_walk_done(d, w, avail);
> >+if (!(avail = w->nbytes))
> 
>   avail = w->nbytes;
>   if (!avail)
> 

Ok.

> > [...]
> >+if (crypto_cipher_blocksize(cipher) != 16) {
> >+*flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
> >+return -EINVAL;
> >+}
> >+
> >+ctx->child = cipher;
> >+
> >+cipher = crypto_spawn_cipher(spawn);
> >+if (IS_ERR(cipher))
> >+return PTR_ERR(cipher);
> 
> don't you want to free ctx->child on error?

Yes, of course. Fixed. 

> >+
> >+/* this check isn't really needed */
> >+if (crypto_cipher_blocksize(cipher) != 16) {
> >+*flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
> >+return -EINVAL;
> >+}
> 
> and here both.

Fixed.

> Right now you should get the same algo but I don't thing that a check
> will hurt.

Agree.

> > [...]
> >+if (alg->cra_alignmask < 7) inst->alg.cra_alignmask = 7;
> >+else inst->alg.cra_alignmask = alg->cra_alignmask;
> >+inst->alg.cra_type = &crypto_blkcipher_type;
> >+
> >+if (!(alg->cra_blocksize % 4))
> >+inst->alg.cra_alignmask |= 3;
> 
> please do
> 
> if (a)
>  do_on_a();
> else
>  do_on_b();

Ok.

> besides that, what are you trying to do? The if() makes sure that the
> alignmask is atleast 7 (0b111). And then, depending on the block size
> you might set the lower two bits (3 is 0b11) which are allready set.

Mmmm, I don't know why I did that. It is probably safe to assume that
alg->cra_alignmask = 2^n - 1 for some n, so I will remove the second if.

> >+inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
> >+inst->alg.cra_blkcipher.min_keysize = 2*alg->cra_cipher.cia_min_keysize;
> >+inst->alg.cr

Re: [PATCH] an XTS blockcipher mode implementation without partial blocks

2007-09-07 Thread rsnel
Hello,

On Fri, Sep 07, 2007 at 08:38:32PM +0200, Sebastian Siewior wrote:
> [...]
>
> >Christoph encountered a deadlock after a few hours and 16GB of data (on
> >an aes-xts-plain partition). Assuming there is an error in xts.c, is
> >there an obvious way of finding it?
> 
> Haven't seen any locks in your code, so your part may be fine. How do I
> use this? 
> 
> cryptsetup -c aes-xts 
> 
> or?

for example: 
cryptsetup --hash sha256 -s 256 -c aes-xts-plain create test /dev/some_partition

The 'plain'-iv should give an on-disk format compatible with the
requirements of IEEE1619/D16. Internally the 256-bit key is split in two
128-bit AES keys. Other allowed key sizes for aes-xts-* are 2*192=384
bit and 2*256=512 bit. (you may want to use a hash with more bits (I don't know
what cryptsetup does if the hash gives less than keysize bits))

Christoph, is your testing machine stable if you run the same test with
aes-lrw-plain and the same keysize?

Greetings,

Rik.

-- 
Nothing is ever a total loss; it can always serve as a bad example.
-
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html