From adc54d08d0bef13f6baaa5e7f7204ecc569761b2 Mon Sep 17 00:00:00 2001 From: Pascal Brand Date: Thu, 18 Sep 2014 01:42:54 +0200 Subject: [PATCH 1/2] Enable multiple XTS encryption or decryption multiple xts_encrypt() cannot be performed because the tweak is not updated. That means that xts_encrypt(buffer1, tweak) xts_encrypt(buffer2, tweak) is not the same as xts_encrypt(concat(buffer1, buffer2), tweak) Current patch enables such functionalities by updating the tweak as output of the encryption. Note that the tweak is no more constant. The very same modification is performed on xts_decrypt() Signed-off-by: Pascal Brand --- src/headers/tomcrypt_cipher.h | 4 ++-- src/modes/xts/xts_decrypt.c | 7 ++++++- src/modes/xts/xts_encrypt.c | 7 ++++++- src/modes/xts/xts_test.c | 8 +++++--- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/headers/tomcrypt_cipher.h b/src/headers/tomcrypt_cipher.h index a7142a0..edf25c0 100644 --- a/src/headers/tomcrypt_cipher.h +++ b/src/headers/tomcrypt_cipher.h @@ -884,12 +884,12 @@ int xts_start( int cipher, int xts_encrypt( const unsigned char *pt, unsigned long ptlen, unsigned char *ct, - const unsigned char *tweak, + unsigned char *tweak, symmetric_xts *xts); int xts_decrypt( const unsigned char *ct, unsigned long ptlen, unsigned char *pt, - const unsigned char *tweak, + unsigned char *tweak, symmetric_xts *xts); void xts_done(symmetric_xts *xts); diff --git a/src/modes/xts/xts_decrypt.c b/src/modes/xts/xts_decrypt.c index 3e46c53..f73770d 100644 --- a/src/modes/xts/xts_decrypt.c +++ b/src/modes/xts/xts_decrypt.c @@ -60,7 +60,7 @@ static int tweak_uncrypt(const unsigned char *C, unsigned char *P, unsigned char */int xts_decrypt( const unsigned char *ct, unsigned long ptlen, unsigned char *pt, - const unsigned char *tweak, + unsigned char *tweak, symmetric_xts *xts) { unsigned char PP[16], CC[16], T[16]; @@ -130,6 +130,11 @@ static int tweak_uncrypt(const unsigned char *C, unsigned char *P, unsigned char } } + /* Decrypt the tweak back */ + if ((err = cipher_descriptor[xts->cipher].ecb_decrypt(T, tweak, &xts->key2)) != CRYPT_OK) { + return err; + } + return CRYPT_OK; } diff --git a/src/modes/xts/xts_encrypt.c b/src/modes/xts/xts_encrypt.c index ab53d3c..6474b13 100644 --- a/src/modes/xts/xts_encrypt.c +++ b/src/modes/xts/xts_encrypt.c @@ -63,7 +63,7 @@ static int tweak_crypt(const unsigned char *P, unsigned char *C, unsigned char * int xts_encrypt( const unsigned char *pt, unsigned long ptlen, unsigned char *ct, - const unsigned char *tweak, + unsigned char *tweak, symmetric_xts *xts) { unsigned char PP[16], CC[16], T[16]; @@ -131,6 +131,11 @@ int xts_encrypt( } } + /* Decrypt the tweak back */ + if ((err = cipher_descriptor[xts->cipher].ecb_decrypt(T, tweak, &xts->key2)) != CRYPT_OK) { + return err; + } + return err; } diff --git a/src/modes/xts/xts_test.c b/src/modes/xts/xts_test.c index b91e0f4..2973f0a 100644 --- a/src/modes/xts/xts_test.c +++ b/src/modes/xts/xts_test.c @@ -142,7 +142,7 @@ int xts_test(void) }, }; - unsigned char OUT[512], T[16]; + unsigned char OUT[512], Torg[16], T[16]; ulong64 seq; symmetric_xts xts; int i, err, idx; @@ -161,9 +161,10 @@ int xts_test(void) } seq = tests[i].seqnum; - STORE64L(seq,T); - XMEMSET(T+8, 0, 8); + STORE64L(seq,Torg); + XMEMSET(Torg+8, 0, 8); + XMEMCPY(T, Torg, sizeof(T)); err = xts_encrypt(tests[i].PTX, tests[i].PTLEN, OUT, T, &xts); if (err != CRYPT_OK) { xts_done(&xts); @@ -175,6 +176,7 @@ int xts_test(void) return CRYPT_FAIL_TESTVECTOR; } + XMEMCPY(T, Torg, sizeof(T)); err = xts_decrypt(tests[i].CTX, tests[i].PTLEN, OUT, T, &xts); if (err != CRYPT_OK) { xts_done(&xts); From 3d905ca17826f5ef4bcbd1a95e571636d797f2da Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Mon, 29 Sep 2014 19:47:18 +0200 Subject: [PATCH 2/2] add testcase for multiple XTS encryption/decryption --- src/modes/xts/xts_test.c | 123 ++++++++++++++++++++++++++++----------- 1 file changed, 90 insertions(+), 33 deletions(-) diff --git a/src/modes/xts/xts_test.c b/src/modes/xts/xts_test.c index 2973f0a..89f00b7 100644 --- a/src/modes/xts/xts_test.c +++ b/src/modes/xts/xts_test.c @@ -12,7 +12,11 @@ #ifdef LTC_XTS_MODE -/** +#if defined(LTC_XTS_TEST_DBG) && !defined(LTC_NO_TEST) +void print_hex(const char* what, const unsigned char* p, const unsigned long l); +#endif + +/** Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects Returns CRYPT_OK upon success. */ @@ -145,49 +149,102 @@ int xts_test(void) unsigned char OUT[512], Torg[16], T[16]; ulong64 seq; symmetric_xts xts; - int i, err, idx; + int i, j, err, idx; + unsigned long len; - /* AES can be under rijndael or aes... try to find it */ + /* AES can be under rijndael or aes... try to find it */ if ((idx = find_cipher("aes")) == -1) { if ((idx = find_cipher("rijndael")) == -1) { return CRYPT_NOP; } } - for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { - err = xts_start(idx, tests[i].key1, tests[i].key2, tests[i].keylen/2, 0, &xts); - if (err != CRYPT_OK) { - return err; - } - - seq = tests[i].seqnum; - STORE64L(seq,Torg); - XMEMSET(Torg+8, 0, 8); + for (j = 0; j < 2; j++) { + for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { + /* skip the cases where + * the length is smaller than 2*blocklen + * or the length is not a multiple of 32 + */ + if ((j == 1) && ((tests[i].PTLEN < 32) || (tests[i].PTLEN % 32))) { + continue; + } + len = tests[i].PTLEN/2; - XMEMCPY(T, Torg, sizeof(T)); - err = xts_encrypt(tests[i].PTX, tests[i].PTLEN, OUT, T, &xts); - if (err != CRYPT_OK) { - xts_done(&xts); - return err; - } + err = xts_start(idx, tests[i].key1, tests[i].key2, tests[i].keylen/2, 0, &xts); + if (err != CRYPT_OK) { + return err; + } - if (XMEMCMP(OUT, tests[i].CTX, tests[i].PTLEN)) { - xts_done(&xts); - return CRYPT_FAIL_TESTVECTOR; - } + seq = tests[i].seqnum; + STORE64L(seq,Torg); + XMEMSET(Torg+8, 0, 8); - XMEMCPY(T, Torg, sizeof(T)); - err = xts_decrypt(tests[i].CTX, tests[i].PTLEN, OUT, T, &xts); - if (err != CRYPT_OK) { - xts_done(&xts); - return err; - } + XMEMCPY(T, Torg, sizeof(T)); + if (j == 0) { + err = xts_encrypt(tests[i].PTX, tests[i].PTLEN, OUT, T, &xts); + if (err != CRYPT_OK) { + xts_done(&xts); + return err; + } + } + else { +#ifdef LTC_XTS_TEST_DBG + printf("\nTestcase #%d with original length %lu and half of it %lu\n", i, tests[i].PTLEN, len); +#endif + err = xts_encrypt(tests[i].PTX, len, OUT, T, &xts); + if (err != CRYPT_OK) { + xts_done(&xts); + return err; + } + err = xts_encrypt(&tests[i].PTX[len], len, &OUT[len], T, &xts); + if (err != CRYPT_OK) { + xts_done(&xts); + return err; + } + } - if (XMEMCMP(OUT, tests[i].PTX, tests[i].PTLEN)) { - xts_done(&xts); - return CRYPT_FAIL_TESTVECTOR; - } - xts_done(&xts); + if (XMEMCMP(OUT, tests[i].CTX, tests[i].PTLEN)) { +#ifdef LTC_XTS_TEST_DBG + printf("\nencrypt\n"); + print_hex("should", tests[i].CTX, tests[i].PTLEN); + print_hex("is", OUT, tests[i].PTLEN); +#endif + xts_done(&xts); + return CRYPT_FAIL_TESTVECTOR; + } + + XMEMCPY(T, Torg, sizeof(T)); + if (j == 0) { + err = xts_decrypt(tests[i].CTX, tests[i].PTLEN, OUT, T, &xts); + if (err != CRYPT_OK) { + xts_done(&xts); + return err; + } + } + else { + err = xts_decrypt(tests[i].CTX, len, OUT, T, &xts); + if (err != CRYPT_OK) { + xts_done(&xts); + return err; + } + err = xts_decrypt(&tests[i].CTX[len], len, &OUT[len], T, &xts); + if (err != CRYPT_OK) { + xts_done(&xts); + return err; + } + } + + if (XMEMCMP(OUT, tests[i].PTX, tests[i].PTLEN)) { +#ifdef LTC_XTS_TEST_DBG + printf("\ndecrypt\n"); + print_hex("should", tests[i].PTX, tests[i].PTLEN); + print_hex("is", OUT, tests[i].PTLEN); +#endif + xts_done(&xts); + return CRYPT_FAIL_TESTVECTOR; + } + xts_done(&xts); + } } return CRYPT_OK; #endif