Linux cryptographic layer development
 help / color / mirror / Atom feed
* [PATCH] an XTS blockcipher mode implementation without partial blocks
@ 2007-09-03 21:45 Rik Snel
  2007-09-05  0:29 ` Sebastian Siewior
  0 siblings, 1 reply; 9+ messages in thread
From: Rik Snel @ 2007-09-03 21:45 UTC (permalink / raw)
  To: linux-crypto; +Cc: christoph.sievers, herbert, Rik Snel

XTS currently considered to be the successor of the LRW mode by the IEEE1619
workgroup. LRW was discarded, because it was not secure if the encyption key
itself is encrypted with LRW.

XTS does not have this problem. The implementation is pretty straightforward,
a new function was added to gf128mul to handle GF(128) elements in ble format.
Four testvectors from the specification
	http://grouper.ieee.org/groups/1619/email/pdf00086.pdf
were added, and they verify on my system.

Signed-off-by: Rik Snel <rsnel@cube.dyndns.org>
---
 crypto/Kconfig            |   11 ++
 crypto/Makefile           |    1 +
 crypto/gf128mul.c         |   11 ++
 crypto/tcrypt.c           |   12 ++
 crypto/tcrypt.h           |  417 +++++++++++++++++++++++++++++++++++++++++++++
 crypto/xts.c              |  277 ++++++++++++++++++++++++++++++
 include/crypto/gf128mul.h |    2 +
 7 files changed, 731 insertions(+), 0 deletions(-)
 create mode 100644 crypto/xts.c

diff --git a/crypto/Kconfig b/crypto/Kconfig
index 3d1a1e2..de94549 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -183,6 +183,17 @@ config CRYPTO_LRW
 	  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_XTS
+	tristate "XTS support (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	select CRYPTO_BLKCIPHER
+	select CRYPTO_MANAGER
+	select CRYPTO_GF128MUL
+	help
+	  XTS: IEEE1619/D16 narrow block cipher use with aes-xts-plain,
+	  key size 256, 384 or 512 bits. This implementation currently
+	  can't handle a sectorsize which is not a multiple of 16 bytes.
+
 config CRYPTO_CRYPTD
 	tristate "Software async crypto daemon"
 	select CRYPTO_ABLKCIPHER
diff --git a/crypto/Makefile b/crypto/Makefile
index 0cf17f1..c4a2bed 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_CRYPTO_ECB) += ecb.o
 obj-$(CONFIG_CRYPTO_CBC) += cbc.o
 obj-$(CONFIG_CRYPTO_PCBC) += pcbc.o
 obj-$(CONFIG_CRYPTO_LRW) += lrw.o
+obj-$(CONFIG_CRYPTO_XTS) += xts.o
 obj-$(CONFIG_CRYPTO_CRYPTD) += cryptd.o
 obj-$(CONFIG_CRYPTO_DES) += des.o
 obj-$(CONFIG_CRYPTO_FCRYPT) += fcrypt.o
diff --git a/crypto/gf128mul.c b/crypto/gf128mul.c
index 0a2aadf..ecbeaa1 100644
--- a/crypto/gf128mul.c
+++ b/crypto/gf128mul.c
@@ -142,6 +142,17 @@ static void gf128mul_x_bbe(be128 *r, const be128 *x)
 	r->b = cpu_to_be64((b << 1) ^ _tt);
 }
 
+void gf128mul_x_ble(be128 *r, const be128 *x)
+{
+	u64 a = le64_to_cpu(x->a);
+	u64 b = le64_to_cpu(x->b);
+	u64 _tt = gf128mul_table_bbe[b >> 63];
+
+	r->a = cpu_to_le64((a << 1) ^ _tt);
+	r->b = cpu_to_le64((b << 1) | (a >> 63));
+}
+EXPORT_SYMBOL(gf128mul_x_ble);
+
 static void gf128mul_x8_lle(be128 *x)
 {
 	u64 a = be64_to_cpu(x->a);
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index 11f9359..d749106 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -955,6 +955,10 @@ static void do_test(void)
 			    AES_LRW_ENC_TEST_VECTORS);
 		test_cipher("lrw(aes)", DECRYPT, aes_lrw_dec_tv_template,
 			    AES_LRW_DEC_TEST_VECTORS);
+		test_cipher("xts(aes)", ENCRYPT, aes_xts_enc_tv_template,
+			    AES_XTS_ENC_TEST_VECTORS);
+		test_cipher("xts(aes)", DECRYPT, aes_xts_dec_tv_template,
+			    AES_XTS_DEC_TEST_VECTORS);
 
 		//CAST5
 		test_cipher("ecb(cast5)", ENCRYPT, cast5_enc_tv_template,
@@ -1132,6 +1136,10 @@ static void do_test(void)
 			    AES_LRW_ENC_TEST_VECTORS);
 		test_cipher("lrw(aes)", DECRYPT, aes_lrw_dec_tv_template,
 			    AES_LRW_DEC_TEST_VECTORS);
+		test_cipher("xts(aes)", ENCRYPT, aes_xts_enc_tv_template,
+			    AES_XTS_ENC_TEST_VECTORS);
+		test_cipher("xts(aes)", DECRYPT, aes_xts_dec_tv_template,
+			    AES_XTS_DEC_TEST_VECTORS);
 		break;
 
 	case 11:
@@ -1307,6 +1315,10 @@ static void do_test(void)
 				  aes_lrw_speed_template);
 		test_cipher_speed("lrw(aes)", DECRYPT, sec, NULL, 0,
 				  aes_lrw_speed_template);
+		test_cipher_speed("xts(aes)", ENCRYPT, sec, NULL, 0,
+				  aes_xts_speed_template);
+		test_cipher_speed("xts(aes)", DECRYPT, sec, NULL, 0,
+				  aes_xts_speed_template);
 		break;
 
 	case 201:
diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h
index 887527b..03a9445 100644
--- a/crypto/tcrypt.h
+++ b/crypto/tcrypt.h
@@ -2144,6 +2144,8 @@ static struct cipher_testvec cast6_dec_tv_template[] = {
 #define AES_CBC_DEC_TEST_VECTORS 2
 #define AES_LRW_ENC_TEST_VECTORS 8
 #define AES_LRW_DEC_TEST_VECTORS 8
+#define AES_XTS_ENC_TEST_VECTORS 4
+#define AES_XTS_DEC_TEST_VECTORS 4
 
 static struct cipher_testvec aes_enc_tv_template[] = {
 	{ /* From FIPS-197 */
@@ -2784,6 +2786,400 @@ static struct cipher_testvec aes_lrw_dec_tv_template[] = {
 	}
 };
 
+static struct cipher_testvec aes_xts_enc_tv_template[] = {
+	/* http://grouper.ieee.org/groups/1619/email/pdf00086.pdf */
+	{ /* XTS-AES 1 */
+		.key    = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.klen   = 32,
+		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.input  = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.ilen   = 32,
+		.result = { 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec,
+			    0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92,
+			    0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85,
+			    0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e },
+		.rlen   = 32,
+	}, { /* XTS-AES 2 */
+		.key    = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			    0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+			    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
+		.klen   = 32,
+		.iv     = { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.input  = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
+		.ilen   = 32,
+		.result = { 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e,
+			    0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b,
+			    0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4,
+			    0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 },
+		.rlen   = 32,
+	}, { /* XTS-AES 3 */
+		.key    = { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
+			    0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
+			    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+			    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
+		.klen   = 32,
+		.iv     = { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.input  = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
+		.ilen   = 32,
+		.result = { 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a,
+			    0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2,
+			    0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53,
+			    0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 },
+		.rlen   = 32,
+	}, { /* XTS-AES 4 */
+		.key    = { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45,
+			    0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26,
+			    0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93,
+			    0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95 },
+		.klen   = 32,
+		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.input  = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+			    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+			    0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+			    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+			    0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+			    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+			    0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+			    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+			    0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+			    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+			    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+			    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+			    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+			    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+			    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+			    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+			    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+			    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+			    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+			    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+			    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+			    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+			    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+			    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+			    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+			    0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+			    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+			    0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+			    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+			    0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+			    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+			    0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+			    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+			    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+			    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+			    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+			    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+			    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+			    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+			    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+			    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+			    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+			    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+			    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+			    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+			    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff },
+		.ilen   = 512,
+		.result = { 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76,
+			    0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2,
+			    0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25,
+			    0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c,
+			    0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f,
+			    0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00,
+			    0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad,
+			    0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12,
+			    0x32, 0x80, 0x63, 0xfd, 0x2a, 0xab, 0x53, 0xe5,
+			    0xea, 0x1e, 0x0a, 0x9f, 0x33, 0x25, 0x00, 0xa5,
+			    0xdf, 0x94, 0x87, 0xd0, 0x7a, 0x5c, 0x92, 0xcc,
+			    0x51, 0x2c, 0x88, 0x66, 0xc7, 0xe8, 0x60, 0xce,
+			    0x93, 0xfd, 0xf1, 0x66, 0xa2, 0x49, 0x12, 0xb4,
+			    0x22, 0x97, 0x61, 0x46, 0xae, 0x20, 0xce, 0x84,
+			    0x6b, 0xb7, 0xdc, 0x9b, 0xa9, 0x4a, 0x76, 0x7a,
+			    0xae, 0xf2, 0x0c, 0x0d, 0x61, 0xad, 0x02, 0x65,
+			    0x5e, 0xa9, 0x2d, 0xc4, 0xc4, 0xe4, 0x1a, 0x89,
+			    0x52, 0xc6, 0x51, 0xd3, 0x31, 0x74, 0xbe, 0x51,
+			    0xa1, 0x0c, 0x42, 0x11, 0x10, 0xe6, 0xd8, 0x15,
+			    0x88, 0xed, 0xe8, 0x21, 0x03, 0xa2, 0x52, 0xd8,
+			    0xa7, 0x50, 0xe8, 0x76, 0x8d, 0xef, 0xff, 0xed,
+			    0x91, 0x22, 0x81, 0x0a, 0xae, 0xb9, 0x9f, 0x91,
+			    0x72, 0xaf, 0x82, 0xb6, 0x04, 0xdc, 0x4b, 0x8e,
+			    0x51, 0xbc, 0xb0, 0x82, 0x35, 0xa6, 0xf4, 0x34,
+			    0x13, 0x32, 0xe4, 0xca, 0x60, 0x48, 0x2a, 0x4b,
+			    0xa1, 0xa0, 0x3b, 0x3e, 0x65, 0x00, 0x8f, 0xc5,
+			    0xda, 0x76, 0xb7, 0x0b, 0xf1, 0x69, 0x0d, 0xb4,
+			    0xea, 0xe2, 0x9c, 0x5f, 0x1b, 0xad, 0xd0, 0x3c,
+			    0x5c, 0xcf, 0x2a, 0x55, 0xd7, 0x05, 0xdd, 0xcd,
+			    0x86, 0xd4, 0x49, 0x51, 0x1c, 0xeb, 0x7e, 0xc3,
+			    0x0b, 0xf1, 0x2b, 0x1f, 0xa3, 0x5b, 0x91, 0x3f,
+			    0x9f, 0x74, 0x7a, 0x8a, 0xfd, 0x1b, 0x13, 0x0e,
+			    0x94, 0xbf, 0xf9, 0x4e, 0xff, 0xd0, 0x1a, 0x91,
+			    0x73, 0x5c, 0xa1, 0x72, 0x6a, 0xcd, 0x0b, 0x19,
+			    0x7c, 0x4e, 0x5b, 0x03, 0x39, 0x36, 0x97, 0xe1,
+			    0x26, 0x82, 0x6f, 0xb6, 0xbb, 0xde, 0x8e, 0xcc,
+			    0x1e, 0x08, 0x29, 0x85, 0x16, 0xe2, 0xc9, 0xed,
+			    0x03, 0xff, 0x3c, 0x1b, 0x78, 0x60, 0xf6, 0xde,
+			    0x76, 0xd4, 0xce, 0xcd, 0x94, 0xc8, 0x11, 0x98,
+			    0x55, 0xef, 0x52, 0x97, 0xca, 0x67, 0xe9, 0xf3,
+			    0xe7, 0xff, 0x72, 0xb1, 0xe9, 0x97, 0x85, 0xca,
+			    0x0a, 0x7e, 0x77, 0x20, 0xc5, 0xb3, 0x6d, 0xc6,
+			    0xd7, 0x2c, 0xac, 0x95, 0x74, 0xc8, 0xcb, 0xbc,
+			    0x2f, 0x80, 0x1e, 0x23, 0xe5, 0x6f, 0xd3, 0x44,
+			    0xb0, 0x7f, 0x22, 0x15, 0x4b, 0xeb, 0xa0, 0xf0,
+			    0x8c, 0xe8, 0x89, 0x1e, 0x64, 0x3e, 0xd9, 0x95,
+			    0xc9, 0x4d, 0x9a, 0x69, 0xc9, 0xf1, 0xb5, 0xf4,
+			    0x99, 0x02, 0x7a, 0x78, 0x57, 0x2a, 0xee, 0xbd,
+			    0x74, 0xd2, 0x0c, 0xc3, 0x98, 0x81, 0xc2, 0x13,
+			    0xee, 0x77, 0x0b, 0x10, 0x10, 0xe4, 0xbe, 0xa7,
+			    0x18, 0x84, 0x69, 0x77, 0xae, 0x11, 0x9f, 0x7a,
+			    0x02, 0x3a, 0xb5, 0x8c, 0xca, 0x0a, 0xd7, 0x52,
+			    0xaf, 0xe6, 0x56, 0xbb, 0x3c, 0x17, 0x25, 0x6a,
+			    0x9f, 0x6e, 0x9b, 0xf1, 0x9f, 0xdd, 0x5a, 0x38,
+			    0xfc, 0x82, 0xbb, 0xe8, 0x72, 0xc5, 0x53, 0x9e,
+			    0xdb, 0x60, 0x9e, 0xf4, 0xf7, 0x9c, 0x20, 0x3e,
+			    0xbb, 0x14, 0x0f, 0x2e, 0x58, 0x3c, 0xb2, 0xad,
+			    0x15, 0xb4, 0xaa, 0x5b, 0x65, 0x50, 0x16, 0xa8,
+			    0x44, 0x92, 0x77, 0xdb, 0xd4, 0x77, 0xef, 0x2c,
+			    0x8d, 0x6c, 0x01, 0x7d, 0xb7, 0x38, 0xb1, 0x8d,
+			    0xeb, 0x4a, 0x42, 0x7d, 0x19, 0x23, 0xce, 0x3f,
+			    0xf2, 0x62, 0x73, 0x57, 0x79, 0xa4, 0x18, 0xf2,
+			    0x0a, 0x28, 0x2d, 0xf9, 0x20, 0x14, 0x7b, 0xea,
+			    0xbe, 0x42, 0x1e, 0xe5, 0x31, 0x9d, 0x05, 0x68 },
+		.rlen   = 512,
+	}
+};
+
+static struct cipher_testvec aes_xts_dec_tv_template[] = {
+	/* http://grouper.ieee.org/groups/1619/email/pdf00086.pdf */
+	{ /* XTS-AES 1 */
+		.key    = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.klen   = 32,
+		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.input = { 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec,
+			   0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92,
+			   0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85,
+			   0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e },
+		.ilen   = 32,
+		.result  = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.rlen   = 32,
+	}, { /* XTS-AES 2 */
+		.key    = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			    0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+			    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
+		.klen   = 32,
+		.iv     = { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.input  = { 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e,
+			    0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b,
+			    0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4,
+			    0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 },
+		.ilen   = 32,
+		.result = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
+		.rlen   = 32,
+	}, { /* XTS-AES 3 */
+		.key    = { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
+			    0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
+			    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+			    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
+		.klen   = 32,
+		.iv     = { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.input = { 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a,
+			    0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2,
+			    0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53,
+			    0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 },
+		.ilen   = 32,
+		.result  = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
+		.rlen   = 32,
+	}, { /* XTS-AES 4 */
+		.key    = { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45,
+			    0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26,
+			    0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93,
+			    0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95 },
+		.klen   = 32,
+		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.input  = { 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76,
+			    0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2,
+			    0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25,
+			    0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c,
+			    0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f,
+			    0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00,
+			    0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad,
+			    0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12,
+			    0x32, 0x80, 0x63, 0xfd, 0x2a, 0xab, 0x53, 0xe5,
+			    0xea, 0x1e, 0x0a, 0x9f, 0x33, 0x25, 0x00, 0xa5,
+			    0xdf, 0x94, 0x87, 0xd0, 0x7a, 0x5c, 0x92, 0xcc,
+			    0x51, 0x2c, 0x88, 0x66, 0xc7, 0xe8, 0x60, 0xce,
+			    0x93, 0xfd, 0xf1, 0x66, 0xa2, 0x49, 0x12, 0xb4,
+			    0x22, 0x97, 0x61, 0x46, 0xae, 0x20, 0xce, 0x84,
+			    0x6b, 0xb7, 0xdc, 0x9b, 0xa9, 0x4a, 0x76, 0x7a,
+			    0xae, 0xf2, 0x0c, 0x0d, 0x61, 0xad, 0x02, 0x65,
+			    0x5e, 0xa9, 0x2d, 0xc4, 0xc4, 0xe4, 0x1a, 0x89,
+			    0x52, 0xc6, 0x51, 0xd3, 0x31, 0x74, 0xbe, 0x51,
+			    0xa1, 0x0c, 0x42, 0x11, 0x10, 0xe6, 0xd8, 0x15,
+			    0x88, 0xed, 0xe8, 0x21, 0x03, 0xa2, 0x52, 0xd8,
+			    0xa7, 0x50, 0xe8, 0x76, 0x8d, 0xef, 0xff, 0xed,
+			    0x91, 0x22, 0x81, 0x0a, 0xae, 0xb9, 0x9f, 0x91,
+			    0x72, 0xaf, 0x82, 0xb6, 0x04, 0xdc, 0x4b, 0x8e,
+			    0x51, 0xbc, 0xb0, 0x82, 0x35, 0xa6, 0xf4, 0x34,
+			    0x13, 0x32, 0xe4, 0xca, 0x60, 0x48, 0x2a, 0x4b,
+			    0xa1, 0xa0, 0x3b, 0x3e, 0x65, 0x00, 0x8f, 0xc5,
+			    0xda, 0x76, 0xb7, 0x0b, 0xf1, 0x69, 0x0d, 0xb4,
+			    0xea, 0xe2, 0x9c, 0x5f, 0x1b, 0xad, 0xd0, 0x3c,
+			    0x5c, 0xcf, 0x2a, 0x55, 0xd7, 0x05, 0xdd, 0xcd,
+			    0x86, 0xd4, 0x49, 0x51, 0x1c, 0xeb, 0x7e, 0xc3,
+			    0x0b, 0xf1, 0x2b, 0x1f, 0xa3, 0x5b, 0x91, 0x3f,
+			    0x9f, 0x74, 0x7a, 0x8a, 0xfd, 0x1b, 0x13, 0x0e,
+			    0x94, 0xbf, 0xf9, 0x4e, 0xff, 0xd0, 0x1a, 0x91,
+			    0x73, 0x5c, 0xa1, 0x72, 0x6a, 0xcd, 0x0b, 0x19,
+			    0x7c, 0x4e, 0x5b, 0x03, 0x39, 0x36, 0x97, 0xe1,
+			    0x26, 0x82, 0x6f, 0xb6, 0xbb, 0xde, 0x8e, 0xcc,
+			    0x1e, 0x08, 0x29, 0x85, 0x16, 0xe2, 0xc9, 0xed,
+			    0x03, 0xff, 0x3c, 0x1b, 0x78, 0x60, 0xf6, 0xde,
+			    0x76, 0xd4, 0xce, 0xcd, 0x94, 0xc8, 0x11, 0x98,
+			    0x55, 0xef, 0x52, 0x97, 0xca, 0x67, 0xe9, 0xf3,
+			    0xe7, 0xff, 0x72, 0xb1, 0xe9, 0x97, 0x85, 0xca,
+			    0x0a, 0x7e, 0x77, 0x20, 0xc5, 0xb3, 0x6d, 0xc6,
+			    0xd7, 0x2c, 0xac, 0x95, 0x74, 0xc8, 0xcb, 0xbc,
+			    0x2f, 0x80, 0x1e, 0x23, 0xe5, 0x6f, 0xd3, 0x44,
+			    0xb0, 0x7f, 0x22, 0x15, 0x4b, 0xeb, 0xa0, 0xf0,
+			    0x8c, 0xe8, 0x89, 0x1e, 0x64, 0x3e, 0xd9, 0x95,
+			    0xc9, 0x4d, 0x9a, 0x69, 0xc9, 0xf1, 0xb5, 0xf4,
+			    0x99, 0x02, 0x7a, 0x78, 0x57, 0x2a, 0xee, 0xbd,
+			    0x74, 0xd2, 0x0c, 0xc3, 0x98, 0x81, 0xc2, 0x13,
+			    0xee, 0x77, 0x0b, 0x10, 0x10, 0xe4, 0xbe, 0xa7,
+			    0x18, 0x84, 0x69, 0x77, 0xae, 0x11, 0x9f, 0x7a,
+			    0x02, 0x3a, 0xb5, 0x8c, 0xca, 0x0a, 0xd7, 0x52,
+			    0xaf, 0xe6, 0x56, 0xbb, 0x3c, 0x17, 0x25, 0x6a,
+			    0x9f, 0x6e, 0x9b, 0xf1, 0x9f, 0xdd, 0x5a, 0x38,
+			    0xfc, 0x82, 0xbb, 0xe8, 0x72, 0xc5, 0x53, 0x9e,
+			    0xdb, 0x60, 0x9e, 0xf4, 0xf7, 0x9c, 0x20, 0x3e,
+			    0xbb, 0x14, 0x0f, 0x2e, 0x58, 0x3c, 0xb2, 0xad,
+			    0x15, 0xb4, 0xaa, 0x5b, 0x65, 0x50, 0x16, 0xa8,
+			    0x44, 0x92, 0x77, 0xdb, 0xd4, 0x77, 0xef, 0x2c,
+			    0x8d, 0x6c, 0x01, 0x7d, 0xb7, 0x38, 0xb1, 0x8d,
+			    0xeb, 0x4a, 0x42, 0x7d, 0x19, 0x23, 0xce, 0x3f,
+			    0xf2, 0x62, 0x73, 0x57, 0x79, 0xa4, 0x18, 0xf2,
+			    0x0a, 0x28, 0x2d, 0xf9, 0x20, 0x14, 0x7b, 0xea,
+			    0xbe, 0x42, 0x1e, 0xe5, 0x31, 0x9d, 0x05, 0x68 },
+		.ilen   = 512,
+		.result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+			    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+			    0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+			    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+			    0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+			    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+			    0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+			    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+			    0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+			    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+			    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+			    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+			    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+			    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+			    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+			    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+			    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+			    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+			    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+			    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+			    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+			    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+			    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+			    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+			    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+			    0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+			    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+			    0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+			    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+			    0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+			    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+			    0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+			    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+			    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+			    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+			    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+			    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+			    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+			    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+			    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+			    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+			    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+			    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+			    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+			    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+			    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff },
+		.rlen   = 512,
+	}
+};
+
 /* Cast5 test vectors from RFC 2144 */
 #define CAST5_ENC_TEST_VECTORS	3
 #define CAST5_DEC_TEST_VECTORS	3
@@ -4193,6 +4589,27 @@ static struct cipher_speed aes_lrw_speed_template[] = {
 	{  .klen = 0, .blen = 0, }
 };
 
+static struct cipher_speed aes_xts_speed_template[] = {
+	{ .klen = 32, .blen = 16, },
+	{ .klen = 32, .blen = 64, },
+	{ .klen = 32, .blen = 256, },
+	{ .klen = 32, .blen = 1024, },
+	{ .klen = 32, .blen = 8192, },
+	{ .klen = 48, .blen = 16, },
+	{ .klen = 48, .blen = 64, },
+	{ .klen = 48, .blen = 256, },
+	{ .klen = 48, .blen = 1024, },
+	{ .klen = 48, .blen = 8192, },
+	{ .klen = 64, .blen = 16, },
+	{ .klen = 64, .blen = 64, },
+	{ .klen = 64, .blen = 256, },
+	{ .klen = 64, .blen = 1024, },
+	{ .klen = 64, .blen = 8192, },
+
+	/* End marker */
+	{  .klen = 0, .blen = 0, }
+};
+
 static struct cipher_speed des3_ede_speed_template[] = {
 	{ .klen = 24, .blen = 16, },
 	{ .klen = 24, .blen = 64, },
diff --git a/crypto/xts.c b/crypto/xts.c
new file mode 100644
index 0000000..7d9a353
--- /dev/null
+++ b/crypto/xts.c
@@ -0,0 +1,277 @@
+/* XTS: as defined in IEEE1619/D16
+ *	http://grouper.ieee.org/groups/1619/email/pdf00086.pdf
+ *	(sector sizes which are not a multiple of 16 bytes are,
+ *	however currently unsupported)
+ *
+ * Copyright (c) 2007 Rik Snel <rsnel@cube.dyndns.org>
+ *
+ * Based om ecb.c
+ * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * 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 <crypto/algapi.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+
+#include <crypto/b128ops.h>
+#include <crypto/gf128mul.h>
+
+struct priv {
+	struct crypto_cipher *child;
+	struct crypto_cipher *tweak;
+};
+
+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->tweak;
+	u32 *flags = &parent->crt_flags;
+	int err;
+
+	/* 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;
+	}
+
+	/* 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;
+	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)))
+		return err;
+	crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
+				     CRYPTO_TFM_RES_MASK);
+
+	return 0;
+}
+
+struct sinfo {
+	be128 t;
+	struct crypto_tfm *tfm;
+	void (*fn)(struct crypto_tfm *, u8 *, const u8 *);
+};
+
+static inline void xts_round(struct sinfo *s, void *dst, const void *src)
+{
+	be128_xor(dst, &s->t, src);		/* PP <- T xor P */
+	s->fn(s->tfm, dst, dst);		/* CC <- E(Key1,PP) */
+	be128_xor(dst, dst, &s->t);		/* C <- T xor CC */
+}
+
+static int crypt(struct blkcipher_desc *d,
+		 struct blkcipher_walk *w, struct priv *ctx,
+		 void (*tw)(struct crypto_tfm *, u8 *, const u8 *),
+		 void (*fn)(struct crypto_tfm *, u8 *, const u8 *))
+{
+	int err;
+	unsigned int avail;
+	const int bs = crypto_cipher_blocksize(ctx->child);
+	struct sinfo s = {
+		.tfm = crypto_cipher_tfm(ctx->child),
+		.fn = fn
+	};
+	be128 *iv;
+	u8 *wsrc;
+	u8 *wdst;
+
+	err = blkcipher_walk_virt(d, w);
+	if (!(avail = w->nbytes))
+		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:
+			xts_round(&s, wdst, wsrc);
+
+			wsrc += bs;
+			wdst += bs;
+		} while ((avail -= bs) >= bs);
+
+		err = blkcipher_walk_done(d, w, avail);
+		if (!(avail = w->nbytes))
+			break;
+
+		wsrc = w->src.virt.addr;
+		wdst = w->dst.virt.addr;
+	}
+
+	return err;
+}
+
+static int encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		   struct scatterlist *src, unsigned int nbytes)
+{
+	struct priv *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct blkcipher_walk w;
+
+	blkcipher_walk_init(&w, dst, src, nbytes);
+	return crypt(desc, &w, ctx, crypto_cipher_alg(ctx->tweak)->cia_encrypt,
+		     crypto_cipher_alg(ctx->child)->cia_encrypt);
+}
+
+static int decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		   struct scatterlist *src, unsigned int nbytes)
+{
+	struct priv *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct blkcipher_walk w;
+
+	blkcipher_walk_init(&w, dst, src, nbytes);
+	return crypt(desc, &w, ctx, crypto_cipher_alg(ctx->tweak)->cia_encrypt,
+		     crypto_cipher_alg(ctx->child)->cia_decrypt);
+}
+
+static int init_tfm(struct crypto_tfm *tfm)
+{
+	struct crypto_cipher *cipher;
+	struct crypto_instance *inst = (void *)tfm->__crt_alg;
+	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
+	struct priv *ctx = crypto_tfm_ctx(tfm);
+	u32 *flags = &tfm->crt_flags;
+
+	cipher = crypto_spawn_cipher(spawn);
+	if (IS_ERR(cipher))
+		return PTR_ERR(cipher);
+
+	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);
+
+	/* this check isn't really needed */
+	if (crypto_cipher_blocksize(cipher) != 16) {
+		*flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
+		return -EINVAL;
+	}
+
+	ctx->tweak = cipher;
+
+	return 0;
+}
+
+static void exit_tfm(struct crypto_tfm *tfm)
+{
+	struct priv *ctx = crypto_tfm_ctx(tfm);
+	crypto_free_cipher(ctx->child);
+	crypto_free_cipher(ctx->tweak);
+}
+
+static struct crypto_instance *alloc(struct rtattr **tb)
+{
+	struct crypto_instance *inst;
+	struct crypto_alg *alg;
+	int err;
+
+	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+	if (err)
+		return ERR_PTR(err);
+
+	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
+				  CRYPTO_ALG_TYPE_MASK);
+	if (IS_ERR(alg))
+		return ERR_PTR(PTR_ERR(alg));
+
+	inst = crypto_alloc_instance("xts", alg);
+	if (IS_ERR(inst))
+		goto out_put_alg;
+
+	inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
+	inst->alg.cra_priority = alg->cra_priority;
+	inst->alg.cra_blocksize = alg->cra_blocksize;
+
+	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;
+	inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
+	inst->alg.cra_blkcipher.min_keysize = 2*alg->cra_cipher.cia_min_keysize;
+	inst->alg.cra_blkcipher.max_keysize = 2*alg->cra_cipher.cia_max_keysize;
+
+	inst->alg.cra_ctxsize = sizeof(struct priv);
+
+	inst->alg.cra_init = init_tfm;
+	inst->alg.cra_exit = exit_tfm;
+
+	inst->alg.cra_blkcipher.setkey = setkey;
+	inst->alg.cra_blkcipher.encrypt = encrypt;
+	inst->alg.cra_blkcipher.decrypt = decrypt;
+
+out_put_alg:
+	crypto_mod_put(alg);
+	return inst;
+}
+
+static void free(struct crypto_instance *inst)
+{
+	crypto_drop_spawn(crypto_instance_ctx(inst));
+	kfree(inst);
+}
+
+static struct crypto_template crypto_tmpl = {
+	.name = "xts",
+	.alloc = alloc,
+	.free = free,
+	.module = THIS_MODULE,
+};
+
+static int __init crypto_module_init(void)
+{
+	return crypto_register_template(&crypto_tmpl);
+}
+
+static void __exit crypto_module_exit(void)
+{
+	crypto_unregister_template(&crypto_tmpl);
+}
+
+module_init(crypto_module_init);
+module_exit(crypto_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("XTS block cipher mode");
diff --git a/include/crypto/gf128mul.h b/include/crypto/gf128mul.h
index 4fd3152..4086b8e 100644
--- a/include/crypto/gf128mul.h
+++ b/include/crypto/gf128mul.h
@@ -161,6 +161,8 @@ void gf128mul_lle(be128 *a, const be128 *b);
 
 void gf128mul_bbe(be128 *a, const be128 *b);
 
+/* multiply by x in ble format, needed by XTS */
+void gf128mul_x_ble(be128 *a, const be128 *b);
 
 /* 4k table optimization */
 
-- 
1.5.2.5

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

* Re: [PATCH] an XTS blockcipher mode implementation without partial blocks
  2007-09-03 21:45 [PATCH] an XTS blockcipher mode implementation without partial blocks Rik Snel
@ 2007-09-05  0:29 ` Sebastian Siewior
  2007-09-06 14:57   ` rsnel
  0 siblings, 1 reply; 9+ messages in thread
From: Sebastian Siewior @ 2007-09-05  0:29 UTC (permalink / raw)
  To: Rik Snel; +Cc: linux-crypto, christoph.sievers, herbert

* Rik Snel | 2007-09-03 23:45:16 [+0200]:

>diff --git a/crypto/xts.c b/crypto/xts.c
>new file mode 100644
>index 0000000..7d9a353
>--- /dev/null
>+++ b/crypto/xts.c
>@@ -0,0 +1,277 @@
>+/* XTS: as defined in IEEE1619/D16
>+ *	http://grouper.ieee.org/groups/1619/email/pdf00086.pdf
>+ *	(sector sizes which are not a multiple of 16 bytes are,
>+ *	however currently unsupported)
>+ *
>+ * Copyright (c) 2007 Rik Snel <rsnel@cube.dyndns.org>
>+ *
>+ * Based om ecb.c
>+ * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
>+ *
>+ * 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 <crypto/algapi.h>
>+#include <linux/err.h>
>+#include <linux/init.h>
>+#include <linux/kernel.h>
>+#include <linux/module.h>
>+#include <linux/scatterlist.h>
>+#include <linux/slab.h>
>+
>+#include <crypto/b128ops.h>
>+#include <crypto/gf128mul.h>
>+
>+struct priv {
>+	struct crypto_cipher *child;
>+	struct crypto_cipher *tweak;
>+};
>+
>+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->tweak;
>+	u32 *flags = &parent->crt_flags;
>+	int err;
>+
>+	/* 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.

>+
>+	/* 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;

>+	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)))
...

>+		return err;
>+	crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
>+				     CRYPTO_TFM_RES_MASK);
>+
>+	return 0;
>+}
>+
>+struct sinfo {
>+	be128 t;
>+	struct crypto_tfm *tfm;
>+	void (*fn)(struct crypto_tfm *, u8 *, const u8 *);
>+};
>+
>+static inline void xts_round(struct sinfo *s, void *dst, const void *src)
>+{
>+	be128_xor(dst, &s->t, src);		/* PP <- T xor P */
>+	s->fn(s->tfm, dst, dst);		/* CC <- E(Key1,PP) */
>+	be128_xor(dst, dst, &s->t);		/* C <- T xor CC */
>+}
>+
>+static int crypt(struct blkcipher_desc *d,
>+		 struct blkcipher_walk *w, struct priv *ctx,
>+		 void (*tw)(struct crypto_tfm *, u8 *, const u8 *),
>+		 void (*fn)(struct crypto_tfm *, u8 *, const u8 *))
>+{
>+	int err;
>+	unsigned int avail;
>+	const int bs = crypto_cipher_blocksize(ctx->child);
>+	struct sinfo s = {
>+		.tfm = crypto_cipher_tfm(ctx->child),
>+		.fn = fn
>+	};
>+	be128 *iv;
>+	u8 *wsrc;
>+	u8 *wdst;
>+
>+	err = blkcipher_walk_virt(d, w);
>+	if (!(avail = w->nbytes))
...
>+		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.

>+			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)

>+			break;
>+
>+		wsrc = w->src.virt.addr;
>+		wdst = w->dst.virt.addr;
>+	}
>+
>+	return err;
>+}
>+
>+static int encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
>+		   struct scatterlist *src, unsigned int nbytes)
>+{
>+	struct priv *ctx = crypto_blkcipher_ctx(desc->tfm);
>+	struct blkcipher_walk w;
>+
>+	blkcipher_walk_init(&w, dst, src, nbytes);
>+	return crypt(desc, &w, ctx, crypto_cipher_alg(ctx->tweak)->cia_encrypt,
>+		     crypto_cipher_alg(ctx->child)->cia_encrypt);
>+}
>+
>+static int decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
>+		   struct scatterlist *src, unsigned int nbytes)
>+{
>+	struct priv *ctx = crypto_blkcipher_ctx(desc->tfm);
>+	struct blkcipher_walk w;
>+
>+	blkcipher_walk_init(&w, dst, src, nbytes);
>+	return crypt(desc, &w, ctx, crypto_cipher_alg(ctx->tweak)->cia_encrypt,
>+		     crypto_cipher_alg(ctx->child)->cia_decrypt);
>+}
>+
>+static int init_tfm(struct crypto_tfm *tfm)
>+{
>+	struct crypto_cipher *cipher;
>+	struct crypto_instance *inst = (void *)tfm->__crt_alg;
>+	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
>+	struct priv *ctx = crypto_tfm_ctx(tfm);
>+	u32 *flags = &tfm->crt_flags;
>+
>+	cipher = crypto_spawn_cipher(spawn);
>+	if (IS_ERR(cipher))
>+		return PTR_ERR(cipher);
>+
>+	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?

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

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

>+
>+	ctx->tweak = cipher;
>+
>+	return 0;
>+}
>+
>+static void exit_tfm(struct crypto_tfm *tfm)
>+{
>+	struct priv *ctx = crypto_tfm_ctx(tfm);
>+	crypto_free_cipher(ctx->child);
>+	crypto_free_cipher(ctx->tweak);
>+}
>+
>+static struct crypto_instance *alloc(struct rtattr **tb)
>+{
>+	struct crypto_instance *inst;
>+	struct crypto_alg *alg;
>+	int err;
>+
>+	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
>+	if (err)
>+		return ERR_PTR(err);
>+
>+	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
>+				  CRYPTO_ALG_TYPE_MASK);
>+	if (IS_ERR(alg))
>+		return ERR_PTR(PTR_ERR(alg));
>+
>+	inst = crypto_alloc_instance("xts", alg);
>+	if (IS_ERR(inst))
>+		goto out_put_alg;
>+
>+	inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
>+	inst->alg.cra_priority = alg->cra_priority;
>+	inst->alg.cra_blocksize = alg->cra_blocksize;
>+
>+	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();

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.


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

a space between the operator might not be a bad idea.

>+
>+	inst->alg.cra_ctxsize = sizeof(struct priv);
>+
>+	inst->alg.cra_init = init_tfm;
>+	inst->alg.cra_exit = exit_tfm;
>+
>+	inst->alg.cra_blkcipher.setkey = setkey;
>+	inst->alg.cra_blkcipher.encrypt = encrypt;
>+	inst->alg.cra_blkcipher.decrypt = decrypt;
>+
>+out_put_alg:
>+	crypto_mod_put(alg);
>+	return inst;
>+}
>+
>+static void free(struct crypto_instance *inst)
>+{
>+	crypto_drop_spawn(crypto_instance_ctx(inst));
>+	kfree(inst);
>+}
>+
>+static struct crypto_template crypto_tmpl = {
>+	.name = "xts",
>+	.alloc = alloc,
>+	.free = free,
>+	.module = THIS_MODULE,
>+};
>+
>+static int __init crypto_module_init(void)
>+{
>+	return crypto_register_template(&crypto_tmpl);
>+}
>+
>+static void __exit crypto_module_exit(void)
>+{
>+	crypto_unregister_template(&crypto_tmpl);
>+}
>+
>+module_init(crypto_module_init);
>+module_exit(crypto_module_exit);
>+
>+MODULE_LICENSE("GPL");
>+MODULE_DESCRIPTION("XTS block cipher mode");

The other things are looking fine to me. You might want to consider
using ./scripts/checkpatch.pl on your patch the next time :)

Sebastian

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

* Re: [PATCH] an XTS blockcipher mode implementation without partial blocks
  2007-09-05  0:29 ` Sebastian Siewior
@ 2007-09-06 14:57   ` rsnel
  2007-09-07  6:19     ` Herbert Xu
  2007-09-07 18:38     ` Sebastian Siewior
  0 siblings, 2 replies; 9+ messages in thread
From: rsnel @ 2007-09-06 14:57 UTC (permalink / raw)
  To: linux-crypto, christoph.sievers, herbert

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.cra_blkcipher.max_keysize = 2*alg->cra_cipher.cia_max_keysize;
> 
> a space between the operator might not be a bad idea.

I wanted it to fit in 80 columns, will change.
> 
> > [...]
> >+MODULE_LICENSE("GPL");
> >+MODULE_DESCRIPTION("XTS block cipher mode");
> 
> The other things are looking fine to me. You might want to consider
> using ./scripts/checkpatch.pl on your patch the next time :)

I did just that, and it catched a (void*) should be (void *).

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?

Is my re-usage of *spawn (in init_tfm) the right way to get two
instances of the blockcipher?

A patch which fixes everything except the goto in crypt() will follow.

Greetings,

Rik.

-- 
Nothing is ever a total loss; it can always serve as a bad example.

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

* [PATCH] an XTS blockcipher mode implementation without partial blocks
@ 2007-09-06 15:03 Rik Snel
  2007-09-12 19:26 ` Sebastian Siewior
  2007-09-19 12:24 ` Herbert Xu
  0 siblings, 2 replies; 9+ messages in thread
From: Rik Snel @ 2007-09-06 15:03 UTC (permalink / raw)
  To: linux-crypto; +Cc: christoph.sievers, herbert, Rik Snel

XTS currently considered to be the successor of the LRW mode by the IEEE1619
workgroup. LRW was discarded, because it was not secure if the encyption key
itself is encrypted with LRW.

XTS does not have this problem. The implementation is pretty straightforward,
a new function was added to gf128mul to handle GF(128) elements in ble format.
Four testvectors from the specification
	http://grouper.ieee.org/groups/1619/email/pdf00086.pdf
were added, and they verify on my system.

Signed-off-by: Rik Snel <rsnel@cube.dyndns.org>
---
 crypto/Kconfig            |   11 ++
 crypto/Makefile           |    1 +
 crypto/gf128mul.c         |   11 ++
 crypto/tcrypt.c           |   12 ++
 crypto/tcrypt.h           |  417 +++++++++++++++++++++++++++++++++++++++++++++
 crypto/xts.c              |  292 +++++++++++++++++++++++++++++++
 include/crypto/gf128mul.h |    2 +
 7 files changed, 746 insertions(+), 0 deletions(-)
 create mode 100644 crypto/xts.c

diff --git a/crypto/Kconfig b/crypto/Kconfig
index 3d1a1e2..de94549 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -183,6 +183,17 @@ config CRYPTO_LRW
 	  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_XTS
+	tristate "XTS support (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	select CRYPTO_BLKCIPHER
+	select CRYPTO_MANAGER
+	select CRYPTO_GF128MUL
+	help
+	  XTS: IEEE1619/D16 narrow block cipher use with aes-xts-plain,
+	  key size 256, 384 or 512 bits. This implementation currently
+	  can't handle a sectorsize which is not a multiple of 16 bytes.
+
 config CRYPTO_CRYPTD
 	tristate "Software async crypto daemon"
 	select CRYPTO_ABLKCIPHER
diff --git a/crypto/Makefile b/crypto/Makefile
index 0cf17f1..c4a2bed 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_CRYPTO_ECB) += ecb.o
 obj-$(CONFIG_CRYPTO_CBC) += cbc.o
 obj-$(CONFIG_CRYPTO_PCBC) += pcbc.o
 obj-$(CONFIG_CRYPTO_LRW) += lrw.o
+obj-$(CONFIG_CRYPTO_XTS) += xts.o
 obj-$(CONFIG_CRYPTO_CRYPTD) += cryptd.o
 obj-$(CONFIG_CRYPTO_DES) += des.o
 obj-$(CONFIG_CRYPTO_FCRYPT) += fcrypt.o
diff --git a/crypto/gf128mul.c b/crypto/gf128mul.c
index 0a2aadf..ecbeaa1 100644
--- a/crypto/gf128mul.c
+++ b/crypto/gf128mul.c
@@ -142,6 +142,17 @@ static void gf128mul_x_bbe(be128 *r, const be128 *x)
 	r->b = cpu_to_be64((b << 1) ^ _tt);
 }
 
+void gf128mul_x_ble(be128 *r, const be128 *x)
+{
+	u64 a = le64_to_cpu(x->a);
+	u64 b = le64_to_cpu(x->b);
+	u64 _tt = gf128mul_table_bbe[b >> 63];
+
+	r->a = cpu_to_le64((a << 1) ^ _tt);
+	r->b = cpu_to_le64((b << 1) | (a >> 63));
+}
+EXPORT_SYMBOL(gf128mul_x_ble);
+
 static void gf128mul_x8_lle(be128 *x)
 {
 	u64 a = be64_to_cpu(x->a);
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index 11f9359..d749106 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -955,6 +955,10 @@ static void do_test(void)
 			    AES_LRW_ENC_TEST_VECTORS);
 		test_cipher("lrw(aes)", DECRYPT, aes_lrw_dec_tv_template,
 			    AES_LRW_DEC_TEST_VECTORS);
+		test_cipher("xts(aes)", ENCRYPT, aes_xts_enc_tv_template,
+			    AES_XTS_ENC_TEST_VECTORS);
+		test_cipher("xts(aes)", DECRYPT, aes_xts_dec_tv_template,
+			    AES_XTS_DEC_TEST_VECTORS);
 
 		//CAST5
 		test_cipher("ecb(cast5)", ENCRYPT, cast5_enc_tv_template,
@@ -1132,6 +1136,10 @@ static void do_test(void)
 			    AES_LRW_ENC_TEST_VECTORS);
 		test_cipher("lrw(aes)", DECRYPT, aes_lrw_dec_tv_template,
 			    AES_LRW_DEC_TEST_VECTORS);
+		test_cipher("xts(aes)", ENCRYPT, aes_xts_enc_tv_template,
+			    AES_XTS_ENC_TEST_VECTORS);
+		test_cipher("xts(aes)", DECRYPT, aes_xts_dec_tv_template,
+			    AES_XTS_DEC_TEST_VECTORS);
 		break;
 
 	case 11:
@@ -1307,6 +1315,10 @@ static void do_test(void)
 				  aes_lrw_speed_template);
 		test_cipher_speed("lrw(aes)", DECRYPT, sec, NULL, 0,
 				  aes_lrw_speed_template);
+		test_cipher_speed("xts(aes)", ENCRYPT, sec, NULL, 0,
+				  aes_xts_speed_template);
+		test_cipher_speed("xts(aes)", DECRYPT, sec, NULL, 0,
+				  aes_xts_speed_template);
 		break;
 
 	case 201:
diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h
index 887527b..03a9445 100644
--- a/crypto/tcrypt.h
+++ b/crypto/tcrypt.h
@@ -2144,6 +2144,8 @@ static struct cipher_testvec cast6_dec_tv_template[] = {
 #define AES_CBC_DEC_TEST_VECTORS 2
 #define AES_LRW_ENC_TEST_VECTORS 8
 #define AES_LRW_DEC_TEST_VECTORS 8
+#define AES_XTS_ENC_TEST_VECTORS 4
+#define AES_XTS_DEC_TEST_VECTORS 4
 
 static struct cipher_testvec aes_enc_tv_template[] = {
 	{ /* From FIPS-197 */
@@ -2784,6 +2786,400 @@ static struct cipher_testvec aes_lrw_dec_tv_template[] = {
 	}
 };
 
+static struct cipher_testvec aes_xts_enc_tv_template[] = {
+	/* http://grouper.ieee.org/groups/1619/email/pdf00086.pdf */
+	{ /* XTS-AES 1 */
+		.key    = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.klen   = 32,
+		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.input  = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.ilen   = 32,
+		.result = { 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec,
+			    0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92,
+			    0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85,
+			    0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e },
+		.rlen   = 32,
+	}, { /* XTS-AES 2 */
+		.key    = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			    0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+			    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
+		.klen   = 32,
+		.iv     = { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.input  = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
+		.ilen   = 32,
+		.result = { 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e,
+			    0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b,
+			    0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4,
+			    0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 },
+		.rlen   = 32,
+	}, { /* XTS-AES 3 */
+		.key    = { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
+			    0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
+			    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+			    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
+		.klen   = 32,
+		.iv     = { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.input  = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
+		.ilen   = 32,
+		.result = { 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a,
+			    0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2,
+			    0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53,
+			    0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 },
+		.rlen   = 32,
+	}, { /* XTS-AES 4 */
+		.key    = { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45,
+			    0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26,
+			    0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93,
+			    0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95 },
+		.klen   = 32,
+		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.input  = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+			    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+			    0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+			    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+			    0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+			    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+			    0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+			    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+			    0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+			    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+			    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+			    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+			    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+			    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+			    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+			    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+			    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+			    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+			    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+			    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+			    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+			    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+			    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+			    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+			    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+			    0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+			    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+			    0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+			    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+			    0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+			    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+			    0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+			    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+			    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+			    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+			    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+			    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+			    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+			    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+			    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+			    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+			    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+			    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+			    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+			    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+			    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff },
+		.ilen   = 512,
+		.result = { 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76,
+			    0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2,
+			    0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25,
+			    0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c,
+			    0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f,
+			    0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00,
+			    0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad,
+			    0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12,
+			    0x32, 0x80, 0x63, 0xfd, 0x2a, 0xab, 0x53, 0xe5,
+			    0xea, 0x1e, 0x0a, 0x9f, 0x33, 0x25, 0x00, 0xa5,
+			    0xdf, 0x94, 0x87, 0xd0, 0x7a, 0x5c, 0x92, 0xcc,
+			    0x51, 0x2c, 0x88, 0x66, 0xc7, 0xe8, 0x60, 0xce,
+			    0x93, 0xfd, 0xf1, 0x66, 0xa2, 0x49, 0x12, 0xb4,
+			    0x22, 0x97, 0x61, 0x46, 0xae, 0x20, 0xce, 0x84,
+			    0x6b, 0xb7, 0xdc, 0x9b, 0xa9, 0x4a, 0x76, 0x7a,
+			    0xae, 0xf2, 0x0c, 0x0d, 0x61, 0xad, 0x02, 0x65,
+			    0x5e, 0xa9, 0x2d, 0xc4, 0xc4, 0xe4, 0x1a, 0x89,
+			    0x52, 0xc6, 0x51, 0xd3, 0x31, 0x74, 0xbe, 0x51,
+			    0xa1, 0x0c, 0x42, 0x11, 0x10, 0xe6, 0xd8, 0x15,
+			    0x88, 0xed, 0xe8, 0x21, 0x03, 0xa2, 0x52, 0xd8,
+			    0xa7, 0x50, 0xe8, 0x76, 0x8d, 0xef, 0xff, 0xed,
+			    0x91, 0x22, 0x81, 0x0a, 0xae, 0xb9, 0x9f, 0x91,
+			    0x72, 0xaf, 0x82, 0xb6, 0x04, 0xdc, 0x4b, 0x8e,
+			    0x51, 0xbc, 0xb0, 0x82, 0x35, 0xa6, 0xf4, 0x34,
+			    0x13, 0x32, 0xe4, 0xca, 0x60, 0x48, 0x2a, 0x4b,
+			    0xa1, 0xa0, 0x3b, 0x3e, 0x65, 0x00, 0x8f, 0xc5,
+			    0xda, 0x76, 0xb7, 0x0b, 0xf1, 0x69, 0x0d, 0xb4,
+			    0xea, 0xe2, 0x9c, 0x5f, 0x1b, 0xad, 0xd0, 0x3c,
+			    0x5c, 0xcf, 0x2a, 0x55, 0xd7, 0x05, 0xdd, 0xcd,
+			    0x86, 0xd4, 0x49, 0x51, 0x1c, 0xeb, 0x7e, 0xc3,
+			    0x0b, 0xf1, 0x2b, 0x1f, 0xa3, 0x5b, 0x91, 0x3f,
+			    0x9f, 0x74, 0x7a, 0x8a, 0xfd, 0x1b, 0x13, 0x0e,
+			    0x94, 0xbf, 0xf9, 0x4e, 0xff, 0xd0, 0x1a, 0x91,
+			    0x73, 0x5c, 0xa1, 0x72, 0x6a, 0xcd, 0x0b, 0x19,
+			    0x7c, 0x4e, 0x5b, 0x03, 0x39, 0x36, 0x97, 0xe1,
+			    0x26, 0x82, 0x6f, 0xb6, 0xbb, 0xde, 0x8e, 0xcc,
+			    0x1e, 0x08, 0x29, 0x85, 0x16, 0xe2, 0xc9, 0xed,
+			    0x03, 0xff, 0x3c, 0x1b, 0x78, 0x60, 0xf6, 0xde,
+			    0x76, 0xd4, 0xce, 0xcd, 0x94, 0xc8, 0x11, 0x98,
+			    0x55, 0xef, 0x52, 0x97, 0xca, 0x67, 0xe9, 0xf3,
+			    0xe7, 0xff, 0x72, 0xb1, 0xe9, 0x97, 0x85, 0xca,
+			    0x0a, 0x7e, 0x77, 0x20, 0xc5, 0xb3, 0x6d, 0xc6,
+			    0xd7, 0x2c, 0xac, 0x95, 0x74, 0xc8, 0xcb, 0xbc,
+			    0x2f, 0x80, 0x1e, 0x23, 0xe5, 0x6f, 0xd3, 0x44,
+			    0xb0, 0x7f, 0x22, 0x15, 0x4b, 0xeb, 0xa0, 0xf0,
+			    0x8c, 0xe8, 0x89, 0x1e, 0x64, 0x3e, 0xd9, 0x95,
+			    0xc9, 0x4d, 0x9a, 0x69, 0xc9, 0xf1, 0xb5, 0xf4,
+			    0x99, 0x02, 0x7a, 0x78, 0x57, 0x2a, 0xee, 0xbd,
+			    0x74, 0xd2, 0x0c, 0xc3, 0x98, 0x81, 0xc2, 0x13,
+			    0xee, 0x77, 0x0b, 0x10, 0x10, 0xe4, 0xbe, 0xa7,
+			    0x18, 0x84, 0x69, 0x77, 0xae, 0x11, 0x9f, 0x7a,
+			    0x02, 0x3a, 0xb5, 0x8c, 0xca, 0x0a, 0xd7, 0x52,
+			    0xaf, 0xe6, 0x56, 0xbb, 0x3c, 0x17, 0x25, 0x6a,
+			    0x9f, 0x6e, 0x9b, 0xf1, 0x9f, 0xdd, 0x5a, 0x38,
+			    0xfc, 0x82, 0xbb, 0xe8, 0x72, 0xc5, 0x53, 0x9e,
+			    0xdb, 0x60, 0x9e, 0xf4, 0xf7, 0x9c, 0x20, 0x3e,
+			    0xbb, 0x14, 0x0f, 0x2e, 0x58, 0x3c, 0xb2, 0xad,
+			    0x15, 0xb4, 0xaa, 0x5b, 0x65, 0x50, 0x16, 0xa8,
+			    0x44, 0x92, 0x77, 0xdb, 0xd4, 0x77, 0xef, 0x2c,
+			    0x8d, 0x6c, 0x01, 0x7d, 0xb7, 0x38, 0xb1, 0x8d,
+			    0xeb, 0x4a, 0x42, 0x7d, 0x19, 0x23, 0xce, 0x3f,
+			    0xf2, 0x62, 0x73, 0x57, 0x79, 0xa4, 0x18, 0xf2,
+			    0x0a, 0x28, 0x2d, 0xf9, 0x20, 0x14, 0x7b, 0xea,
+			    0xbe, 0x42, 0x1e, 0xe5, 0x31, 0x9d, 0x05, 0x68 },
+		.rlen   = 512,
+	}
+};
+
+static struct cipher_testvec aes_xts_dec_tv_template[] = {
+	/* http://grouper.ieee.org/groups/1619/email/pdf00086.pdf */
+	{ /* XTS-AES 1 */
+		.key    = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.klen   = 32,
+		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.input = { 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec,
+			   0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92,
+			   0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85,
+			   0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e },
+		.ilen   = 32,
+		.result  = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.rlen   = 32,
+	}, { /* XTS-AES 2 */
+		.key    = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			    0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+			    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
+		.klen   = 32,
+		.iv     = { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.input  = { 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e,
+			    0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b,
+			    0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4,
+			    0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 },
+		.ilen   = 32,
+		.result = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
+		.rlen   = 32,
+	}, { /* XTS-AES 3 */
+		.key    = { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
+			    0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
+			    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+			    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
+		.klen   = 32,
+		.iv     = { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.input = { 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a,
+			    0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2,
+			    0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53,
+			    0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 },
+		.ilen   = 32,
+		.result  = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
+		.rlen   = 32,
+	}, { /* XTS-AES 4 */
+		.key    = { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45,
+			    0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26,
+			    0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93,
+			    0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95 },
+		.klen   = 32,
+		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.input  = { 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76,
+			    0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2,
+			    0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25,
+			    0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c,
+			    0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f,
+			    0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00,
+			    0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad,
+			    0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12,
+			    0x32, 0x80, 0x63, 0xfd, 0x2a, 0xab, 0x53, 0xe5,
+			    0xea, 0x1e, 0x0a, 0x9f, 0x33, 0x25, 0x00, 0xa5,
+			    0xdf, 0x94, 0x87, 0xd0, 0x7a, 0x5c, 0x92, 0xcc,
+			    0x51, 0x2c, 0x88, 0x66, 0xc7, 0xe8, 0x60, 0xce,
+			    0x93, 0xfd, 0xf1, 0x66, 0xa2, 0x49, 0x12, 0xb4,
+			    0x22, 0x97, 0x61, 0x46, 0xae, 0x20, 0xce, 0x84,
+			    0x6b, 0xb7, 0xdc, 0x9b, 0xa9, 0x4a, 0x76, 0x7a,
+			    0xae, 0xf2, 0x0c, 0x0d, 0x61, 0xad, 0x02, 0x65,
+			    0x5e, 0xa9, 0x2d, 0xc4, 0xc4, 0xe4, 0x1a, 0x89,
+			    0x52, 0xc6, 0x51, 0xd3, 0x31, 0x74, 0xbe, 0x51,
+			    0xa1, 0x0c, 0x42, 0x11, 0x10, 0xe6, 0xd8, 0x15,
+			    0x88, 0xed, 0xe8, 0x21, 0x03, 0xa2, 0x52, 0xd8,
+			    0xa7, 0x50, 0xe8, 0x76, 0x8d, 0xef, 0xff, 0xed,
+			    0x91, 0x22, 0x81, 0x0a, 0xae, 0xb9, 0x9f, 0x91,
+			    0x72, 0xaf, 0x82, 0xb6, 0x04, 0xdc, 0x4b, 0x8e,
+			    0x51, 0xbc, 0xb0, 0x82, 0x35, 0xa6, 0xf4, 0x34,
+			    0x13, 0x32, 0xe4, 0xca, 0x60, 0x48, 0x2a, 0x4b,
+			    0xa1, 0xa0, 0x3b, 0x3e, 0x65, 0x00, 0x8f, 0xc5,
+			    0xda, 0x76, 0xb7, 0x0b, 0xf1, 0x69, 0x0d, 0xb4,
+			    0xea, 0xe2, 0x9c, 0x5f, 0x1b, 0xad, 0xd0, 0x3c,
+			    0x5c, 0xcf, 0x2a, 0x55, 0xd7, 0x05, 0xdd, 0xcd,
+			    0x86, 0xd4, 0x49, 0x51, 0x1c, 0xeb, 0x7e, 0xc3,
+			    0x0b, 0xf1, 0x2b, 0x1f, 0xa3, 0x5b, 0x91, 0x3f,
+			    0x9f, 0x74, 0x7a, 0x8a, 0xfd, 0x1b, 0x13, 0x0e,
+			    0x94, 0xbf, 0xf9, 0x4e, 0xff, 0xd0, 0x1a, 0x91,
+			    0x73, 0x5c, 0xa1, 0x72, 0x6a, 0xcd, 0x0b, 0x19,
+			    0x7c, 0x4e, 0x5b, 0x03, 0x39, 0x36, 0x97, 0xe1,
+			    0x26, 0x82, 0x6f, 0xb6, 0xbb, 0xde, 0x8e, 0xcc,
+			    0x1e, 0x08, 0x29, 0x85, 0x16, 0xe2, 0xc9, 0xed,
+			    0x03, 0xff, 0x3c, 0x1b, 0x78, 0x60, 0xf6, 0xde,
+			    0x76, 0xd4, 0xce, 0xcd, 0x94, 0xc8, 0x11, 0x98,
+			    0x55, 0xef, 0x52, 0x97, 0xca, 0x67, 0xe9, 0xf3,
+			    0xe7, 0xff, 0x72, 0xb1, 0xe9, 0x97, 0x85, 0xca,
+			    0x0a, 0x7e, 0x77, 0x20, 0xc5, 0xb3, 0x6d, 0xc6,
+			    0xd7, 0x2c, 0xac, 0x95, 0x74, 0xc8, 0xcb, 0xbc,
+			    0x2f, 0x80, 0x1e, 0x23, 0xe5, 0x6f, 0xd3, 0x44,
+			    0xb0, 0x7f, 0x22, 0x15, 0x4b, 0xeb, 0xa0, 0xf0,
+			    0x8c, 0xe8, 0x89, 0x1e, 0x64, 0x3e, 0xd9, 0x95,
+			    0xc9, 0x4d, 0x9a, 0x69, 0xc9, 0xf1, 0xb5, 0xf4,
+			    0x99, 0x02, 0x7a, 0x78, 0x57, 0x2a, 0xee, 0xbd,
+			    0x74, 0xd2, 0x0c, 0xc3, 0x98, 0x81, 0xc2, 0x13,
+			    0xee, 0x77, 0x0b, 0x10, 0x10, 0xe4, 0xbe, 0xa7,
+			    0x18, 0x84, 0x69, 0x77, 0xae, 0x11, 0x9f, 0x7a,
+			    0x02, 0x3a, 0xb5, 0x8c, 0xca, 0x0a, 0xd7, 0x52,
+			    0xaf, 0xe6, 0x56, 0xbb, 0x3c, 0x17, 0x25, 0x6a,
+			    0x9f, 0x6e, 0x9b, 0xf1, 0x9f, 0xdd, 0x5a, 0x38,
+			    0xfc, 0x82, 0xbb, 0xe8, 0x72, 0xc5, 0x53, 0x9e,
+			    0xdb, 0x60, 0x9e, 0xf4, 0xf7, 0x9c, 0x20, 0x3e,
+			    0xbb, 0x14, 0x0f, 0x2e, 0x58, 0x3c, 0xb2, 0xad,
+			    0x15, 0xb4, 0xaa, 0x5b, 0x65, 0x50, 0x16, 0xa8,
+			    0x44, 0x92, 0x77, 0xdb, 0xd4, 0x77, 0xef, 0x2c,
+			    0x8d, 0x6c, 0x01, 0x7d, 0xb7, 0x38, 0xb1, 0x8d,
+			    0xeb, 0x4a, 0x42, 0x7d, 0x19, 0x23, 0xce, 0x3f,
+			    0xf2, 0x62, 0x73, 0x57, 0x79, 0xa4, 0x18, 0xf2,
+			    0x0a, 0x28, 0x2d, 0xf9, 0x20, 0x14, 0x7b, 0xea,
+			    0xbe, 0x42, 0x1e, 0xe5, 0x31, 0x9d, 0x05, 0x68 },
+		.ilen   = 512,
+		.result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+			    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+			    0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+			    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+			    0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+			    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+			    0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+			    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+			    0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+			    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+			    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+			    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+			    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+			    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+			    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+			    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+			    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+			    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+			    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+			    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+			    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+			    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+			    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+			    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+			    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+			    0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+			    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+			    0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+			    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+			    0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+			    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+			    0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+			    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+			    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+			    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+			    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+			    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+			    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+			    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+			    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+			    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+			    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+			    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+			    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+			    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+			    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff },
+		.rlen   = 512,
+	}
+};
+
 /* Cast5 test vectors from RFC 2144 */
 #define CAST5_ENC_TEST_VECTORS	3
 #define CAST5_DEC_TEST_VECTORS	3
@@ -4193,6 +4589,27 @@ static struct cipher_speed aes_lrw_speed_template[] = {
 	{  .klen = 0, .blen = 0, }
 };
 
+static struct cipher_speed aes_xts_speed_template[] = {
+	{ .klen = 32, .blen = 16, },
+	{ .klen = 32, .blen = 64, },
+	{ .klen = 32, .blen = 256, },
+	{ .klen = 32, .blen = 1024, },
+	{ .klen = 32, .blen = 8192, },
+	{ .klen = 48, .blen = 16, },
+	{ .klen = 48, .blen = 64, },
+	{ .klen = 48, .blen = 256, },
+	{ .klen = 48, .blen = 1024, },
+	{ .klen = 48, .blen = 8192, },
+	{ .klen = 64, .blen = 16, },
+	{ .klen = 64, .blen = 64, },
+	{ .klen = 64, .blen = 256, },
+	{ .klen = 64, .blen = 1024, },
+	{ .klen = 64, .blen = 8192, },
+
+	/* End marker */
+	{  .klen = 0, .blen = 0, }
+};
+
 static struct cipher_speed des3_ede_speed_template[] = {
 	{ .klen = 24, .blen = 16, },
 	{ .klen = 24, .blen = 64, },
diff --git a/crypto/xts.c b/crypto/xts.c
new file mode 100644
index 0000000..8eb08bf
--- /dev/null
+++ b/crypto/xts.c
@@ -0,0 +1,292 @@
+/* XTS: as defined in IEEE1619/D16
+ *	http://grouper.ieee.org/groups/1619/email/pdf00086.pdf
+ *	(sector sizes which are not a multiple of 16 bytes are,
+ *	however currently unsupported)
+ *
+ * Copyright (c) 2007 Rik Snel <rsnel@cube.dyndns.org>
+ *
+ * Based om ecb.c
+ * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * 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 <crypto/algapi.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+
+#include <crypto/b128ops.h>
+#include <crypto/gf128mul.h>
+
+struct priv {
+	struct crypto_cipher *child;
+	struct crypto_cipher *tweak;
+};
+
+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->tweak;
+	u32 *flags = &parent->crt_flags;
+	int err;
+
+	/* key consists of keys of equal size concatenated, therefore
+	 * the length must be even */
+	if (keylen % 2) {
+		/* tell the user why there was an error */
+		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+		return -EINVAL;
+	}
+
+	/* 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);
+	err = crypto_cipher_setkey(child, key + keylen/2, keylen/2);
+	if (err)
+		return err;
+
+	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);
+	err = crypto_cipher_setkey(child, key, keylen/2);
+	if (err)
+		return err;
+
+	crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
+				     CRYPTO_TFM_RES_MASK);
+
+	return 0;
+}
+
+struct sinfo {
+	be128 t;
+	struct crypto_tfm *tfm;
+	void (*fn)(struct crypto_tfm *, u8 *, const u8 *);
+};
+
+static inline void xts_round(struct sinfo *s, void *dst, const void *src)
+{
+	be128_xor(dst, &s->t, src);		/* PP <- T xor P */
+	s->fn(s->tfm, dst, dst);		/* CC <- E(Key1,PP) */
+	be128_xor(dst, dst, &s->t);		/* C <- T xor CC */
+}
+
+static int crypt(struct blkcipher_desc *d,
+		 struct blkcipher_walk *w, struct priv *ctx,
+		 void (*tw)(struct crypto_tfm *, u8 *, const u8 *),
+		 void (*fn)(struct crypto_tfm *, u8 *, const u8 *))
+{
+	int err;
+	unsigned int avail;
+	const int bs = crypto_cipher_blocksize(ctx->child);
+	struct sinfo s = {
+		.tfm = crypto_cipher_tfm(ctx->child),
+		.fn = fn
+	};
+	be128 *iv;
+	u8 *wsrc;
+	u8 *wdst;
+
+	err = blkcipher_walk_virt(d, w);
+	if (!w->nbytes)
+		return err;
+
+	avail = w->nbytes;
+
+	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:
+			xts_round(&s, wdst, wsrc);
+
+			wsrc += bs;
+			wdst += bs;
+		} while ((avail -= bs) >= bs);
+
+		err = blkcipher_walk_done(d, w, avail);
+		if (!w->nbytes)
+			break;
+
+		avail = w->nbytes;
+
+		wsrc = w->src.virt.addr;
+		wdst = w->dst.virt.addr;
+	}
+
+	return err;
+}
+
+static int encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		   struct scatterlist *src, unsigned int nbytes)
+{
+	struct priv *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct blkcipher_walk w;
+
+	blkcipher_walk_init(&w, dst, src, nbytes);
+	return crypt(desc, &w, ctx, crypto_cipher_alg(ctx->tweak)->cia_encrypt,
+		     crypto_cipher_alg(ctx->child)->cia_encrypt);
+}
+
+static int decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		   struct scatterlist *src, unsigned int nbytes)
+{
+	struct priv *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct blkcipher_walk w;
+
+	blkcipher_walk_init(&w, dst, src, nbytes);
+	return crypt(desc, &w, ctx, crypto_cipher_alg(ctx->tweak)->cia_encrypt,
+		     crypto_cipher_alg(ctx->child)->cia_decrypt);
+}
+
+static int init_tfm(struct crypto_tfm *tfm)
+{
+	struct crypto_cipher *cipher;
+	struct crypto_instance *inst = (void *)tfm->__crt_alg;
+	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
+	struct priv *ctx = crypto_tfm_ctx(tfm);
+	u32 *flags = &tfm->crt_flags;
+
+	cipher = crypto_spawn_cipher(spawn);
+	if (IS_ERR(cipher))
+		return PTR_ERR(cipher);
+
+	if (crypto_cipher_blocksize(cipher) != 16) {
+		*flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
+		crypto_free_cipher(cipher);
+		return -EINVAL;
+	}
+
+	ctx->child = cipher;
+
+	cipher = crypto_spawn_cipher(spawn);
+	if (IS_ERR(cipher)) {
+		crypto_free_cipher(ctx->child);
+		return PTR_ERR(cipher);
+	}
+
+	/* this check isn't really needed, leave it here just in case */
+	if (crypto_cipher_blocksize(cipher) != 16) {
+		crypto_free_cipher(cipher);
+		crypto_free_cipher(ctx->child);
+		*flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
+		return -EINVAL;
+	}
+
+	ctx->tweak = cipher;
+
+	return 0;
+}
+
+static void exit_tfm(struct crypto_tfm *tfm)
+{
+	struct priv *ctx = crypto_tfm_ctx(tfm);
+	crypto_free_cipher(ctx->child);
+	crypto_free_cipher(ctx->tweak);
+}
+
+static struct crypto_instance *alloc(struct rtattr **tb)
+{
+	struct crypto_instance *inst;
+	struct crypto_alg *alg;
+	int err;
+
+	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+	if (err)
+		return ERR_PTR(err);
+
+	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
+				  CRYPTO_ALG_TYPE_MASK);
+	if (IS_ERR(alg))
+		return ERR_PTR(PTR_ERR(alg));
+
+	inst = crypto_alloc_instance("xts", alg);
+	if (IS_ERR(inst))
+		goto out_put_alg;
+
+	inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
+	inst->alg.cra_priority = alg->cra_priority;
+	inst->alg.cra_blocksize = alg->cra_blocksize;
+
+	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;
+
+	inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
+	inst->alg.cra_blkcipher.min_keysize =
+		2 * alg->cra_cipher.cia_min_keysize;
+	inst->alg.cra_blkcipher.max_keysize =
+		2 * alg->cra_cipher.cia_max_keysize;
+
+	inst->alg.cra_ctxsize = sizeof(struct priv);
+
+	inst->alg.cra_init = init_tfm;
+	inst->alg.cra_exit = exit_tfm;
+
+	inst->alg.cra_blkcipher.setkey = setkey;
+	inst->alg.cra_blkcipher.encrypt = encrypt;
+	inst->alg.cra_blkcipher.decrypt = decrypt;
+
+out_put_alg:
+	crypto_mod_put(alg);
+	return inst;
+}
+
+static void free(struct crypto_instance *inst)
+{
+	crypto_drop_spawn(crypto_instance_ctx(inst));
+	kfree(inst);
+}
+
+static struct crypto_template crypto_tmpl = {
+	.name = "xts",
+	.alloc = alloc,
+	.free = free,
+	.module = THIS_MODULE,
+};
+
+static int __init crypto_module_init(void)
+{
+	return crypto_register_template(&crypto_tmpl);
+}
+
+static void __exit crypto_module_exit(void)
+{
+	crypto_unregister_template(&crypto_tmpl);
+}
+
+module_init(crypto_module_init);
+module_exit(crypto_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("XTS block cipher mode");
diff --git a/include/crypto/gf128mul.h b/include/crypto/gf128mul.h
index 4fd3152..4086b8e 100644
--- a/include/crypto/gf128mul.h
+++ b/include/crypto/gf128mul.h
@@ -161,6 +161,8 @@ void gf128mul_lle(be128 *a, const be128 *b);
 
 void gf128mul_bbe(be128 *a, const be128 *b);
 
+/* multiply by x in ble format, needed by XTS */
+void gf128mul_x_ble(be128 *a, const be128 *b);
 
 /* 4k table optimization */
 
-- 
1.5.2.5

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

* Re: [PATCH] an XTS blockcipher mode implementation without partial blocks
  2007-09-06 14:57   ` rsnel
@ 2007-09-07  6:19     ` Herbert Xu
  2007-09-07 18:38     ` Sebastian Siewior
  1 sibling, 0 replies; 9+ messages in thread
From: Herbert Xu @ 2007-09-07  6:19 UTC (permalink / raw)
  To: rsnel; +Cc: linux-crypto, christoph.sievers

On Thu, Sep 06, 2007 at 04:57:26PM +0200, rsnel@cube.dyndns.org wrote:
>
> 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.

Yes this code looks OK to me.

Cheers,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

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

* Re: [PATCH] an XTS blockcipher mode implementation without partial blocks
  2007-09-06 14:57   ` rsnel
  2007-09-07  6:19     ` Herbert Xu
@ 2007-09-07 18:38     ` Sebastian Siewior
  2007-09-07 19:23       ` rsnel
  1 sibling, 1 reply; 9+ messages in thread
From: Sebastian Siewior @ 2007-09-07 18:38 UTC (permalink / raw)
  To: rsnel; +Cc: linux-crypto, christoph.sievers, herbert

* rsnel@cube.dyndns.org | 2007-09-06 16:57:26 [+0200]:

>> 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)

I didn't know that Herbert did it the same way. In that case you are
fine :)

>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?

>Greetings,
>
>Rik.

Sebastian

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

* Re: [PATCH] an XTS blockcipher mode implementation without partial blocks
  2007-09-07 18:38     ` Sebastian Siewior
@ 2007-09-07 19:23       ` rsnel
  0 siblings, 0 replies; 9+ messages in thread
From: rsnel @ 2007-09-07 19:23 UTC (permalink / raw)
  To: linux-crypto, christoph.sievers, herbert

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.

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

* Re: [PATCH] an XTS blockcipher mode implementation without partial blocks
  2007-09-06 15:03 Rik Snel
@ 2007-09-12 19:26 ` Sebastian Siewior
  2007-09-19 12:24 ` Herbert Xu
  1 sibling, 0 replies; 9+ messages in thread
From: Sebastian Siewior @ 2007-09-12 19:26 UTC (permalink / raw)
  To: Rik Snel; +Cc: linux-crypto, christoph.sievers, herbert

Hi Rik,

I played with xts+dm-crypt on a 4GiB partition for a while and my box
did not hang.
I added some comments after init_tfm() where *I* think it is more
readable that way. Using ctx->tweak and ctx->child instead of child in
setkey() might be also better. However, this is my personal taste :)
The patch looks fine from my POV :)

* Rik Snel | 2007-09-06 17:03:42 [+0200]:

>diff --git a/crypto/xts.c b/crypto/xts.c
>new file mode 100644
>index 0000000..8eb08bf
>--- /dev/null
>+++ b/crypto/xts.c
>@@ -0,0 +1,292 @@
>+/* XTS: as defined in IEEE1619/D16
>+ *	http://grouper.ieee.org/groups/1619/email/pdf00086.pdf
>+ *	(sector sizes which are not a multiple of 16 bytes are,
>+ *	however currently unsupported)
>+ *
>+ * Copyright (c) 2007 Rik Snel <rsnel@cube.dyndns.org>
>+ *
>+ * Based om ecb.c
>+ * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
>+ *
>+ * 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 <crypto/algapi.h>
>+#include <linux/err.h>
>+#include <linux/init.h>
>+#include <linux/kernel.h>
>+#include <linux/module.h>
>+#include <linux/scatterlist.h>
>+#include <linux/slab.h>
>+
>+#include <crypto/b128ops.h>
>+#include <crypto/gf128mul.h>
>+
>+struct priv {
>+	struct crypto_cipher *child;
>+	struct crypto_cipher *tweak;
>+};
>+
>+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->tweak;
>+	u32 *flags = &parent->crt_flags;
>+	int err;
>+
>+	/* key consists of keys of equal size concatenated, therefore
>+	 * the length must be even */
>+	if (keylen % 2) {
>+		/* tell the user why there was an error */
>+		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
>+		return -EINVAL;
>+	}
>+
>+	/* 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);
>+	err = crypto_cipher_setkey(child, key + keylen/2, keylen/2);
>+	if (err)
>+		return err;
>+
>+	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);
>+	err = crypto_cipher_setkey(child, key, keylen/2);
>+	if (err)
>+		return err;
>+
>+	crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
>+				     CRYPTO_TFM_RES_MASK);
>+
>+	return 0;
>+}
>+
>+struct sinfo {
>+	be128 t;
>+	struct crypto_tfm *tfm;
>+	void (*fn)(struct crypto_tfm *, u8 *, const u8 *);
>+};
>+
>+static inline void xts_round(struct sinfo *s, void *dst, const void *src)
>+{
>+	be128_xor(dst, &s->t, src);		/* PP <- T xor P */
>+	s->fn(s->tfm, dst, dst);		/* CC <- E(Key1,PP) */
>+	be128_xor(dst, dst, &s->t);		/* C <- T xor CC */
>+}
>+
>+static int crypt(struct blkcipher_desc *d,
>+		 struct blkcipher_walk *w, struct priv *ctx,
>+		 void (*tw)(struct crypto_tfm *, u8 *, const u8 *),
>+		 void (*fn)(struct crypto_tfm *, u8 *, const u8 *))
>+{
>+	int err;
>+	unsigned int avail;
>+	const int bs = crypto_cipher_blocksize(ctx->child);
>+	struct sinfo s = {
>+		.tfm = crypto_cipher_tfm(ctx->child),
>+		.fn = fn
>+	};
>+	be128 *iv;
>+	u8 *wsrc;
>+	u8 *wdst;
>+
>+	err = blkcipher_walk_virt(d, w);
>+	if (!w->nbytes)
>+		return err;
>+
>+	avail = w->nbytes;
>+
>+	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:
>+			xts_round(&s, wdst, wsrc);
>+
>+			wsrc += bs;
>+			wdst += bs;
>+		} while ((avail -= bs) >= bs);
>+
>+		err = blkcipher_walk_done(d, w, avail);
>+		if (!w->nbytes)
>+			break;
>+
>+		avail = w->nbytes;
>+
>+		wsrc = w->src.virt.addr;
>+		wdst = w->dst.virt.addr;
>+	}
>+
>+	return err;
>+}
>+
>+static int encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
>+		   struct scatterlist *src, unsigned int nbytes)
>+{
>+	struct priv *ctx = crypto_blkcipher_ctx(desc->tfm);
>+	struct blkcipher_walk w;
>+
>+	blkcipher_walk_init(&w, dst, src, nbytes);
>+	return crypt(desc, &w, ctx, crypto_cipher_alg(ctx->tweak)->cia_encrypt,
>+		     crypto_cipher_alg(ctx->child)->cia_encrypt);
>+}
>+
>+static int decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
>+		   struct scatterlist *src, unsigned int nbytes)
>+{
>+	struct priv *ctx = crypto_blkcipher_ctx(desc->tfm);
>+	struct blkcipher_walk w;
>+
>+	blkcipher_walk_init(&w, dst, src, nbytes);
>+	return crypt(desc, &w, ctx, crypto_cipher_alg(ctx->tweak)->cia_encrypt,
>+		     crypto_cipher_alg(ctx->child)->cia_decrypt);
>+}
>+
>+static int init_tfm(struct crypto_tfm *tfm)
>+{
>+	struct crypto_cipher *cipher;
>+	struct crypto_instance *inst = (void *)tfm->__crt_alg;
>+	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
>+	struct priv *ctx = crypto_tfm_ctx(tfm);
>+	u32 *flags = &tfm->crt_flags;
>+
>+	cipher = crypto_spawn_cipher(spawn);
>+	if (IS_ERR(cipher))
>+		return PTR_ERR(cipher);
>+
>+	if (crypto_cipher_blocksize(cipher) != 16) {
>+		*flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
>+		crypto_free_cipher(cipher);
>+		return -EINVAL;
>+	}
>+
>+	ctx->child = cipher;
>+
>+	cipher = crypto_spawn_cipher(spawn);
>+	if (IS_ERR(cipher)) {
>+		crypto_free_cipher(ctx->child);
>+		return PTR_ERR(cipher);
>+	}
>+
>+	/* this check isn't really needed, leave it here just in case */
>+	if (crypto_cipher_blocksize(cipher) != 16) {
>+		crypto_free_cipher(cipher);
>+		crypto_free_cipher(ctx->child);
>+		*flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
>+		return -EINVAL;
>+	}
>+
>+	ctx->tweak = cipher;
>+
>+	return 0;
>+}

maybe more readable?

	ctx->child = crypto_spawn_cipher(spawn);
	if (IS_ERR(ctx->child))
		return PTR_ERR(ctx->child);

	if (crypto_cipher_blocksize(ctx->child) != 16) {
		*flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
		err = -EINVAL;
		goto fail_free_child;
	}

	ctx->tweak = crypto_spawn_cipher(spawn);
	if (IS_ERR(ctx->tweak)) {
		err =  PTR_ERR(ctx->tweak);
        goto fail_free_child
	}

	/* this check isn't really needed, leave it here just in case */
	if (crypto_cipher_blocksize(ctx->tweak) != 16) {
		*flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
		ret = -EINVAL;
		goto fail_free_tweak;
	}

	return 0;

fail_free_tweak:
		crypto_free_cipher(ctx->tweak);

fail_free_child:
		crypto_free_cipher(ctx->child);
		return err;

>+
>+static void exit_tfm(struct crypto_tfm *tfm)
>+{
>+	struct priv *ctx = crypto_tfm_ctx(tfm);
>+	crypto_free_cipher(ctx->child);
>+	crypto_free_cipher(ctx->tweak);
>+}
>+
>+static struct crypto_instance *alloc(struct rtattr **tb)
>+{
>+	struct crypto_instance *inst;
>+	struct crypto_alg *alg;
>+	int err;
>+
>+	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
>+	if (err)
>+		return ERR_PTR(err);
>+
>+	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
>+				  CRYPTO_ALG_TYPE_MASK);
>+	if (IS_ERR(alg))
>+		return ERR_PTR(PTR_ERR(alg));
>+
>+	inst = crypto_alloc_instance("xts", alg);
>+	if (IS_ERR(inst))
>+		goto out_put_alg;
>+
>+	inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
>+	inst->alg.cra_priority = alg->cra_priority;
>+	inst->alg.cra_blocksize = alg->cra_blocksize;
>+
>+	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;
>+
>+	inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
>+	inst->alg.cra_blkcipher.min_keysize =
>+		2 * alg->cra_cipher.cia_min_keysize;
>+	inst->alg.cra_blkcipher.max_keysize =
>+		2 * alg->cra_cipher.cia_max_keysize;
>+
>+	inst->alg.cra_ctxsize = sizeof(struct priv);
>+
>+	inst->alg.cra_init = init_tfm;
>+	inst->alg.cra_exit = exit_tfm;
>+
>+	inst->alg.cra_blkcipher.setkey = setkey;
>+	inst->alg.cra_blkcipher.encrypt = encrypt;
>+	inst->alg.cra_blkcipher.decrypt = decrypt;
>+
>+out_put_alg:
>+	crypto_mod_put(alg);
>+	return inst;
>+}
>+
>+static void free(struct crypto_instance *inst)
>+{
>+	crypto_drop_spawn(crypto_instance_ctx(inst));
>+	kfree(inst);
>+}
>+
>+static struct crypto_template crypto_tmpl = {
>+	.name = "xts",
>+	.alloc = alloc,
>+	.free = free,
>+	.module = THIS_MODULE,
>+};
>+
>+static int __init crypto_module_init(void)
>+{
>+	return crypto_register_template(&crypto_tmpl);
>+}
>+
>+static void __exit crypto_module_exit(void)
>+{
>+	crypto_unregister_template(&crypto_tmpl);
>+}
>+
>+module_init(crypto_module_init);
>+module_exit(crypto_module_exit);
>+
>+MODULE_LICENSE("GPL");
>+MODULE_DESCRIPTION("XTS block cipher mode");
aren't you the MODULE_AUTHOR ? :)

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

* Re: [PATCH] an XTS blockcipher mode implementation without partial blocks
  2007-09-06 15:03 Rik Snel
  2007-09-12 19:26 ` Sebastian Siewior
@ 2007-09-19 12:24 ` Herbert Xu
  1 sibling, 0 replies; 9+ messages in thread
From: Herbert Xu @ 2007-09-19 12:24 UTC (permalink / raw)
  To: Rik Snel; +Cc: linux-crypto, christoph.sievers

On Thu, Sep 06, 2007 at 05:03:42PM +0200, Rik Snel wrote:
> XTS currently considered to be the successor of the LRW mode by the IEEE1619
> workgroup. LRW was discarded, because it was not secure if the encyption key
> itself is encrypted with LRW.
> 
> XTS does not have this problem. The implementation is pretty straightforward,
> a new function was added to gf128mul to handle GF(128) elements in ble format.
> Four testvectors from the specification
> 	http://grouper.ieee.org/groups/1619/email/pdf00086.pdf
> were added, and they verify on my system.
> 
> Signed-off-by: Rik Snel <rsnel@cube.dyndns.org>

Nice work.  Thanks Rik!
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

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

end of thread, other threads:[~2007-09-19 12:24 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-09-03 21:45 [PATCH] an XTS blockcipher mode implementation without partial blocks Rik Snel
2007-09-05  0:29 ` Sebastian Siewior
2007-09-06 14:57   ` rsnel
2007-09-07  6:19     ` Herbert Xu
2007-09-07 18:38     ` Sebastian Siewior
2007-09-07 19:23       ` rsnel
  -- strict thread matches above, loose matches on Subject: below --
2007-09-06 15:03 Rik Snel
2007-09-12 19:26 ` Sebastian Siewior
2007-09-19 12:24 ` Herbert Xu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox