[CRYPTO] xts: XTS blockcipher mode implementation without partial blocks
authorRik Snel <rsnel@cube.dyndns.org>
Wed, 19 Sep 2007 12:23:13 +0000 (20:23 +0800)
committerDavid S. Miller <davem@sunset.davemloft.net>
Wed, 10 Oct 2007 23:55:45 +0000 (16:55 -0700)
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>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
crypto/Kconfig
crypto/Makefile
crypto/gf128mul.c
crypto/tcrypt.c
crypto/tcrypt.h
crypto/xts.c [new file with mode: 0644]
include/crypto/gf128mul.h

index 05f46dfdf1856d32c0b42d66eaf99d1b3fafe93c..083d2e1dfc21640e67f6e6f85671323b2f954a97 100644 (file)
@@ -184,6 +184,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
index da256665aae92686507648acf273a914786175cf..e96a07e16bf2eaa5ac96803cdff3cb3e417db540 100644 (file)
@@ -31,6 +31,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
index 0a2aadfa1d850378cc2e2ec6884f8b89c2676318..ecbeaa1f17e1eae7f17b04c05e922283b0472dd1 100644 (file)
@@ -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);
index de6435ea9bf81ad3f14f4f44d1580a697a5bd516..18d489c8b935f3834fdf72743d1e1ef0e2acd457 100644 (file)
@@ -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,
@@ -1138,6 +1142,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:
@@ -1313,6 +1321,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:
index beab3f345584abf342f4047f5824ef88b52e1ba1..ec861388d9a0ac7a42e1bdd142a8aaeecc8fe61e 100644 (file)
@@ -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
@@ -4283,6 +4679,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 (file)
index 0000000..8eb08bf
--- /dev/null
@@ -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");
index 4fd3152024426d6b154b14a855521257a3828918..4086b8ebfafe196ea6320dab05f552eaa49cf3d8 100644 (file)
@@ -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 */