add AES-XTS mode --enable-xts

This commit is contained in:
Jacob Barthelmeh
2017-08-30 17:50:15 -06:00
parent 59358fd91d
commit ef73c1df7c
9 changed files with 991 additions and 0 deletions

View File

@@ -185,6 +185,7 @@ then
enable_psk=yes
enable_idea=yes
enable_cmac=yes
enable_xts=yes
enable_webserver=yes
enable_hc128=yes
enable_rabbit=yes
@@ -1749,6 +1750,17 @@ AS_IF([test "x$ENABLED_CMAC" = "xyes"],
AM_CONDITIONAL([BUILD_CMAC], [test "x$ENABLED_CMAC" = "xyes"])
# AES-XTS
AC_ARG_ENABLE([xts],
[AS_HELP_STRING([--enable-xts],[Enable XTS (default: disabled)])],
[ ENABLED_XTS=$enableval ],
[ ENABLED_XTS=no ]
)
AS_IF([test "x$ENABLED_XTS" = "xyes"],
[AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_XTS -DWOLFSSL_AES_DIRECT"])
# Web Server Build
AC_ARG_ENABLE([webserver],
[AS_HELP_STRING([--enable-webserver],[Enable Web Server (default: disabled)])],

View File

@@ -718,6 +718,9 @@ static void* benchmarks_do(void* args)
bench_aesgcm(1);
#endif
#endif
#ifdef WOLFSSL_AES_XTS
bench_aesxts();
#endif
#ifdef WOLFSSL_AES_COUNTER
bench_aesctr();
#endif
@@ -1337,6 +1340,73 @@ exit:
#endif /* HAVE_AESGCM */
#ifdef WOLFSSL_AES_XTS
void bench_aesxts(void)
{
Aes aes, tweak;
double start;
int i, count, ret;
static unsigned char k1[] = {
0xa1, 0xb9, 0x0c, 0xba, 0x3f, 0x06, 0xac, 0x35,
0x3b, 0x2c, 0x34, 0x38, 0x76, 0x08, 0x17, 0x62,
0x09, 0x09, 0x23, 0x02, 0x6e, 0x91, 0x77, 0x18,
0x15, 0xf2, 0x9d, 0xab, 0x01, 0x93, 0x2f, 0x2f
};
static unsigned char i1[] = {
0x4f, 0xae, 0xf7, 0x11, 0x7c, 0xda, 0x59, 0xc6,
0x6e, 0x4b, 0x92, 0x01, 0x3e, 0x76, 0x8a, 0xd5
};
ret = wc_AesXtsSetKey(&tweak, &aes, k1, sizeof(k1), AES_ENCRYPTION,
HEAP_HINT, devId);
if (ret != 0) {
printf("wc_AesXtsSetKey failed, ret = %d\n", ret);
return;
}
bench_stats_start(&count, &start);
do {
for (i = 0; i < numBlocks; i++) {
if ((ret = wc_AesXtsEncrypt(&tweak, &aes, bench_plain, bench_cipher,
BENCH_SIZE, i1, sizeof(i1))) != 0) {
printf("wc_AesXtsEncrypt failed, ret = %d\n", ret);
return;
}
}
count += i;
} while (bench_stats_sym_check(start));
bench_stats_sym_finish("AES-XTS-enc", 0, count, start, ret);
wc_AesFree(&aes);
wc_AesFree(&tweak);
/* decryption benchmark */
ret = wc_AesXtsSetKey(&tweak, &aes, k1, sizeof(k1), AES_DECRYPTION,
HEAP_HINT, devId);
if (ret != 0) {
printf("wc_AesXtsSetKey failed, ret = %d\n", ret);
return;
}
bench_stats_start(&count, &start);
do {
for (i = 0; i < numBlocks; i++) {
if ((ret = wc_AesXtsDecrypt(&tweak, &aes, bench_plain, bench_cipher,
BENCH_SIZE, i1, sizeof(i1))) != 0) {
printf("wc_AesXtsDecrypt failed, ret = %d\n", ret);
return;
}
}
count += i;
} while (bench_stats_sym_check(start));
bench_stats_sym_finish("AES-XTS-dec", 0, count, start, ret);
wc_AesFree(&aes);
wc_AesFree(&tweak);
}
#endif /* WOLFSSL_AES_XTS */
#ifdef WOLFSSL_AES_COUNTER
void bench_aesctr(void)
{

View File

@@ -50,6 +50,7 @@ void bench_chacha20_poly1305_aead(void);
void bench_aescbc(int);
void bench_aesgcm(int);
void bench_aesccm(void);
void bench_aesxts(void);
void bench_aesctr(void);
void bench_poly1305(void);
void bench_camellia(void);

View File

@@ -1794,6 +1794,9 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
if (!((keylen == 16) || (keylen == 24) || (keylen == 32)))
return BAD_FUNC_ARG;
#ifdef WOLFSSL_AES_XTS
aes->type = (byte)dir;
#endif
aes->keylen = keylen;
aes->rounds = keylen/4 + 6;
XMEMCPY(rk, userKey, keylen);
@@ -1863,6 +1866,9 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
if (aes == NULL)
return BAD_FUNC_ARG;
#ifdef WOLFSSL_AES_XTS
aes->type = (byte)dir;
#endif
aes->keylen = keylen;
aes->rounds = keylen/4 + 6;
XMEMCPY(aes->key, userKey, keylen);
@@ -1882,6 +1888,9 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
aes->rounds = keylen/4 + 6;
XMEMCPY(aes->key, userKey, keylen);
#ifdef WOLFSSL_AES_XTS
aes->type = (byte)dir;
#endif
#ifdef WOLFSSL_AES_COUNTER
aes->left = 0;
#endif /* WOLFSSL_AES_COUNTER */
@@ -1909,6 +1918,9 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
if (rk == NULL)
return BAD_FUNC_ARG;
#ifdef WOLFSSL_AES_XTS
aes->type = (byte)dir;
#endif
#ifdef WOLFSSL_AES_COUNTER
aes->left = 0;
#endif /* WOLFSSL_AES_COUNTER */
@@ -1949,6 +1961,9 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
if (keylen != 16)
return BAD_FUNC_ARG;
#ifdef WOLFSSL_AES_XTS
aes->type = (byte)dir;
#endif
aes->keylen = keylen;
aes->rounds = keylen/4 + 6;
ret = nrf51_aes_set_key(userKey);
@@ -1975,6 +1990,9 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
#ifdef WOLFSSL_AESNI
aes->use_aesni = 0;
#endif /* WOLFSSL_AESNI */
#ifdef WOLFSSL_AES_XTS
aes->type = (byte)dir;
#endif
#ifdef WOLFSSL_AES_COUNTER
aes->left = 0;
#endif /* WOLFSSL_AES_COUNTER */
@@ -2137,6 +2155,9 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
if (keylen > max_key_len) {
return BAD_FUNC_ARG;
}
#endif
#ifdef WOLFSSL_AES_XTS
aes->type = (byte)dir;
#endif
aes->keylen = keylen;
aes->rounds = keylen/4 + 6;
@@ -8010,5 +8031,333 @@ int wc_AesKeyUnWrap(const byte* key, word32 keySz, const byte* in, word32 inSz,
#endif /* HAVE_AES_KEYWRAP */
#ifdef WOLFSSL_AES_XTS
/* Galios Field to use */
#define GF_XTS 0x87
/* This is to help with setting keys to correct encrypt or decrypt type.
*
* tweak AES key for tweak in XTS
* aes AES key for encrypt/decrypt process
* key buffer holding aes key | tweak key
* len length of key buffer in bytes. Should be twice that of key size. i.e.
* 32 for a 16 byte key.
* dir direction, either AES_ENCRYPTION or AES_DECRYPTION
* heap heap hint to use for memory. Can be NULL
* devId id to use with async crypto. Can be 0
*
* Note: is up to user to call wc_AesFree on tweak and aes key when done.
*
* return 0 on success
*/
int wc_AesXtsSetKey(Aes* tweak, Aes* aes, const byte* key, word32 len, int dir,
void* heap, int devId)
{
word32 keySz;
int ret = 0;
if (aes == NULL || tweak == NULL || key == NULL) {
return BAD_FUNC_ARG;
}
if ((ret = wc_AesInit(tweak, heap, devId)) != 0) {
return ret;
}
if ((ret = wc_AesInit(aes, heap, devId)) != 0) {
return ret;
}
keySz = len/2;
if ((ret = wc_AesSetKey(aes, key, keySz, NULL, dir)) == 0) {
ret = wc_AesSetKey(tweak, key + keySz, keySz, NULL, AES_ENCRYPTION);
if (ret != 0) {
wc_AesFree(aes);
}
}
return ret;
}
/* Same process as wc_AesXtsEncrypt but uses a word64 type as the tweak value
* instead of a byte array. This just converts the word64 to a byte array and
* calls wc_AesXtsEncrypt.
*
* tweak AES tweak key to use
* aes AES key to use for block encrypt/decrypt
* out output buffer to hold cipher text
* in input plain text buffer to encrypt
* sz size of both out and in buffers
* sector value to use for tweak
*
* returns 0 on success
*/
int wc_AesXtsEncryptSector(Aes* tweak, Aes* aes, byte* out, const byte* in,
word32 sz, word64 sector)
{
byte* pt;
byte i[AES_BLOCK_SIZE];
XMEMSET(i, 0, AES_BLOCK_SIZE);
pt = (byte*)&sector;
XMEMCPY(i, pt, sizeof(word64));
return wc_AesXtsEncrypt(tweak, aes, out, in, sz,
(const byte*)i, AES_BLOCK_SIZE);
}
/* Same process as wc_AesXtsDecrypt but uses a word64 type as the tweak value
* instead of a byte array. This just converts the word64 to a byte array.
*
* tweak AES tweak key to use
* aes AES key to use for block encrypt/decrypt
* out output buffer to hold plain text
* in input cipher text buffer to encrypt
* sz size of both out and in buffers
* sector value to use for tweak
*
* returns 0 on success
*/
int wc_AesXtsDecryptSector(Aes* tweak, Aes* aes, byte* out, const byte* in, word32 sz,
word64 sector)
{
byte* pt;
byte i[AES_BLOCK_SIZE];
XMEMSET(i, 0, AES_BLOCK_SIZE);
pt = (byte*)&sector;
XMEMCPY(i, pt, sizeof(word64));
return wc_AesXtsDecrypt(tweak, aes, out, in, sz,
(const byte*)i, AES_BLOCK_SIZE);
}
/* AES with XTS mode. (XTS) XEX encryption with Tweak and cipher text Stealing.
*
* tweak AES tweak key to use
* aes AES key to use for block encrypt/decrypt
* out output buffer to hold cipher text
* in input plain text buffer to encrypt
* sz size of both out and in buffers
* i value to use for tweak
* iSz size of i buffer, should always be AES_BLOCK_SIZE but having this input
* adds a sanity check on how the user calls the function.
*
* returns 0 on success
*/
int wc_AesXtsEncrypt(Aes* tweak, Aes* aes, byte* out, const byte* in, word32 sz,
const byte* i, word32 iSz)
{
int ret = 0;
word32 blocks = (sz / AES_BLOCK_SIZE);
if (aes == NULL || tweak == NULL) {
return BAD_FUNC_ARG;
}
if (aes->type != AES_ENCRYPTION || tweak->type != AES_ENCRYPTION) {
WOLFSSL_MSG("Both aes and tweak type should be AES_ENCRYPTION");
return BAD_FUNC_ARG;
}
if (iSz < AES_BLOCK_SIZE) {
return BAD_FUNC_ARG;
}
if (in == NULL && sz > 0) {
return BAD_FUNC_ARG;
}
if (blocks > 0) {
byte tmp[AES_BLOCK_SIZE];
wc_AesEncryptDirect(tweak, tmp, i);
while (blocks > 0) {
word32 j;
byte carry = 0;
byte buf[AES_BLOCK_SIZE];
XMEMCPY(buf, in, AES_BLOCK_SIZE);
xorbuf(buf, tmp, AES_BLOCK_SIZE);
wc_AesEncryptDirect(aes, out, buf);
xorbuf(out, tmp, AES_BLOCK_SIZE);
/* multiply by shift left and propogate carry */
for (j = 0; j < AES_BLOCK_SIZE; j++) {
byte tmpC;
tmpC = (tmp[j] >> 7) & 0x01;
tmp[j] = ((tmp[j] << 1) + carry) & 0xFF;
carry = tmpC;
}
if (carry) {
tmp[0] ^= GF_XTS;
}
carry = 0;
in += AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
sz -= AES_BLOCK_SIZE;
blocks--;
}
/* stealing operation of XTS to handle left overs */
if (sz > 0) {
byte buf[AES_BLOCK_SIZE];
XMEMCPY(buf, out - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
if (sz >= AES_BLOCK_SIZE) { /* extra sanity check before copy */
return BUFFER_E;
}
XMEMCPY(out, buf, sz);
XMEMCPY(buf, in, sz);
xorbuf(buf, tmp, AES_BLOCK_SIZE);
wc_AesEncryptDirect(aes, out - AES_BLOCK_SIZE, buf);
xorbuf(out - AES_BLOCK_SIZE, tmp, AES_BLOCK_SIZE);
}
}
else {
WOLFSSL_MSG("Plain text input too small for encryption");
return BAD_FUNC_ARG;
}
return ret;
}
/* Same process as encryption but Aes key is AES_DECRYPTION type.
*
* tweak AES tweak key to use
* aes AES key to use for block encrypt/decrypt
* out output buffer to hold plain text
* in input cipher text buffer to decrypt
* sz size of both out and in buffers
* i value to use for tweak
* iSz size of i buffer, should always be AES_BLOCK_SIZE but having this input
* adds a sanity check on how the user calls the function.
*
* returns 0 on success
*/
int wc_AesXtsDecrypt(Aes* tweak, Aes* aes, byte* out, const byte* in, word32 sz,
const byte* i, word32 iSz)
{
int ret = 0;
word32 blocks = (sz / AES_BLOCK_SIZE);
if (aes == NULL || tweak == NULL) {
return BAD_FUNC_ARG;
}
if (aes->type != AES_DECRYPTION || tweak->type != AES_ENCRYPTION) {
WOLFSSL_MSG("aes param should be decryption type and tweak encryption");
return BAD_FUNC_ARG;
}
if (iSz < AES_BLOCK_SIZE) {
return BAD_FUNC_ARG;
}
if (in == NULL && sz > 0) {
return BAD_FUNC_ARG;
}
if (blocks > 0) {
word32 j;
byte carry = 0;
byte tmp[AES_BLOCK_SIZE];
byte stl = (sz % AES_BLOCK_SIZE);
wc_AesEncryptDirect(tweak, tmp, i);
/* if Stealing then break out of loop one block early to handle special
* case */
if (stl > 0) {
blocks--;
}
while (blocks > 0) {
byte buf[AES_BLOCK_SIZE];
XMEMCPY(buf, in, AES_BLOCK_SIZE);
xorbuf(buf, tmp, AES_BLOCK_SIZE);
wc_AesDecryptDirect(aes, out, buf);
xorbuf(out, tmp, AES_BLOCK_SIZE);
/* multiply by shift left and propogate carry */
for (j = 0; j < AES_BLOCK_SIZE; j++) {
byte tmpC;
tmpC = (tmp[j] >> 7) & 0x01;
tmp[j] = ((tmp[j] << 1) + carry) & 0xFF;
carry = tmpC;
}
if (carry) {
tmp[0] ^= GF_XTS;
}
carry = 0;
in += AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
sz -= AES_BLOCK_SIZE;
blocks--;
}
/* stealing operation of XTS to handle left overs */
if (sz > 0) {
byte buf[AES_BLOCK_SIZE];
byte tmp2[AES_BLOCK_SIZE];
/* multiply by shift left and propogate carry */
for (j = 0; j < AES_BLOCK_SIZE; j++) {
byte tmpC;
tmpC = (tmp[j] >> 7) & 0x01;
tmp2[j] = ((tmp[j] << 1) + carry) & 0xFF;
carry = tmpC;
}
if (carry) {
tmp2[0] ^= GF_XTS;
}
XMEMCPY(buf, in, AES_BLOCK_SIZE);
xorbuf(buf, tmp2, AES_BLOCK_SIZE);
wc_AesDecryptDirect(aes, out, buf);
xorbuf(out, tmp2, AES_BLOCK_SIZE);
/* tmp2 holds partial | last */
XMEMCPY(tmp2, out, AES_BLOCK_SIZE);
in += AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
sz -= AES_BLOCK_SIZE;
/* Make buffer with end of cipher text | last */
XMEMCPY(buf, tmp2, AES_BLOCK_SIZE);
if (sz >= AES_BLOCK_SIZE) { /* extra sanity check before copy */
return BUFFER_E;
}
XMEMCPY(buf, in, sz);
XMEMCPY(out, tmp2, sz);
xorbuf(buf, tmp, AES_BLOCK_SIZE);
wc_AesDecryptDirect(aes, tmp2, buf);
xorbuf(tmp2, tmp, AES_BLOCK_SIZE);
XMEMCPY(out - AES_BLOCK_SIZE, tmp2, AES_BLOCK_SIZE);
}
}
else {
WOLFSSL_MSG("Plain text input too small for encryption");
return BAD_FUNC_ARG;
}
return ret;
}
#endif /* WOLFSSL_AES_XTS */
#endif /* HAVE_FIPS */
#endif /* !NO_AES */

View File

@@ -172,6 +172,9 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen,
}
#endif
#ifdef WOLFSSL_AES_XTS
aes->type = dir;
#endif
#ifdef WOLFSSL_AES_COUNTER
aes->left = 0;
#endif /* WOLFSSL_AES_COUNTER */

View File

@@ -75,6 +75,9 @@ WOLFSSL_API int wc_AesSetKey(Aes* aes, const byte* key, word32 len, const byte*
}
XMEMCPY(aes->key, key, len) ;
#ifdef WOLFSSL_AES_XTS
aes->type = dir;
#endif
#ifdef WOLFSSL_AES_COUNTER
aes->left = 0;
#endif /* WOLFSSL_AES_COUNTER */

View File

@@ -4202,6 +4202,521 @@ static int aes_key_size_test(void)
return 0;
}
#if defined(WOLFSSL_AES_XTS)
/* test vectors from http://csrc.nist.gov/groups/STM/cavp/block-cipher-modes.html */
static int aes_xts_128_test(void)
{
Aes aes;
Aes tweak;
int ret = 0;
unsigned char buf[AES_BLOCK_SIZE * 2];
unsigned char cipher[AES_BLOCK_SIZE * 2];
/* 128 key tests */
static unsigned char k1[] = {
0xa1, 0xb9, 0x0c, 0xba, 0x3f, 0x06, 0xac, 0x35,
0x3b, 0x2c, 0x34, 0x38, 0x76, 0x08, 0x17, 0x62,
0x09, 0x09, 0x23, 0x02, 0x6e, 0x91, 0x77, 0x18,
0x15, 0xf2, 0x9d, 0xab, 0x01, 0x93, 0x2f, 0x2f
};
static unsigned char i1[] = {
0x4f, 0xae, 0xf7, 0x11, 0x7c, 0xda, 0x59, 0xc6,
0x6e, 0x4b, 0x92, 0x01, 0x3e, 0x76, 0x8a, 0xd5
};
static unsigned char p1[] = {
0xeb, 0xab, 0xce, 0x95, 0xb1, 0x4d, 0x3c, 0x8d,
0x6f, 0xb3, 0x50, 0x39, 0x07, 0x90, 0x31, 0x1c
};
/* plain text test of partial block is not from NIST test vector list */
static unsigned char pp[] = {
0xeb, 0xab, 0xce, 0x95, 0xb1, 0x4d, 0x3c, 0x8d,
0x6f, 0xb3, 0x50, 0x39, 0x07, 0x90, 0x31, 0x1c,
0x6e, 0x4b, 0x92, 0x01, 0x3e, 0x76, 0x8a, 0xd5
};
static unsigned char c1[] = {
0x77, 0x8a, 0xe8, 0xb4, 0x3c, 0xb9, 0x8d, 0x5a,
0x82, 0x50, 0x81, 0xd5, 0xbe, 0x47, 0x1c, 0x63
};
static unsigned char k2[] = {
0x39, 0x25, 0x79, 0x05, 0xdf, 0xcc, 0x77, 0x76,
0x6c, 0x87, 0x0a, 0x80, 0x6a, 0x60, 0xe3, 0xc0,
0x93, 0xd1, 0x2a, 0xcf, 0xcb, 0x51, 0x42, 0xfa,
0x09, 0x69, 0x89, 0x62, 0x5b, 0x60, 0xdb, 0x16
};
static unsigned char i2[] = {
0x5c, 0xf7, 0x9d, 0xb6, 0xc5, 0xcd, 0x99, 0x1a,
0x1c, 0x78, 0x81, 0x42, 0x24, 0x95, 0x1e, 0x84
};
static unsigned char p2[] = {
0xbd, 0xc5, 0x46, 0x8f, 0xbc, 0x8d, 0x50, 0xa1,
0x0d, 0x1c, 0x85, 0x7f, 0x79, 0x1c, 0x5c, 0xba,
0xb3, 0x81, 0x0d, 0x0d, 0x73, 0xcf, 0x8f, 0x20,
0x46, 0xb1, 0xd1, 0x9e, 0x7d, 0x5d, 0x8a, 0x56
};
static unsigned char c2[] = {
0xd6, 0xbe, 0x04, 0x6d, 0x41, 0xf2, 0x3b, 0x5e,
0xd7, 0x0b, 0x6b, 0x3d, 0x5c, 0x8e, 0x66, 0x23,
0x2b, 0xe6, 0xb8, 0x07, 0xd4, 0xdc, 0xc6, 0x0e,
0xff, 0x8d, 0xbc, 0x1d, 0x9f, 0x7f, 0xc8, 0x22
};
XMEMSET(buf, 0, sizeof(buf));
if (wc_AesXtsSetKey(&tweak, &aes, k2, sizeof(k2), AES_ENCRYPTION,
HEAP_HINT, devId) != 0)
return -4000;
ret = wc_AesXtsEncrypt(&tweak, &aes, buf, p2, sizeof(p2), i2, sizeof(i2));
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE);
#endif
if (ret != 0)
return -4001;
if (XMEMCMP(c2, buf, sizeof(c2)))
return -4002;
XMEMSET(buf, 0, sizeof(buf));
if (wc_AesXtsSetKey(&tweak, &aes, k1, sizeof(k1), AES_ENCRYPTION,
HEAP_HINT, devId) != 0)
return -4003;
ret = wc_AesXtsEncrypt(&tweak, &aes, buf, p1, sizeof(p1), i1, sizeof(i1));
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE);
#endif
if (ret != 0)
return -4004;
if (XMEMCMP(c1, buf, AES_BLOCK_SIZE))
return -4005;
/* partial block encryption test */
XMEMSET(cipher, 0, sizeof(cipher));
ret = wc_AesXtsEncrypt(&tweak, &aes, cipher, pp, sizeof(pp), i1, sizeof(i1));
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE);
#endif
if (ret != 0)
return -4006;
wc_AesFree(&aes);
wc_AesFree(&tweak);
/* partial block decrypt test */
XMEMSET(buf, 0, sizeof(buf));
if (wc_AesXtsSetKey(&tweak, &aes, k1, sizeof(k1), AES_DECRYPTION,
HEAP_HINT, devId) != 0)
return -4007;
ret = wc_AesXtsDecrypt(&tweak, &aes, buf, cipher, sizeof(pp), i1, sizeof(i1));
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE);
#endif
if (ret != 0)
return -4008;
if (XMEMCMP(pp, buf, sizeof(pp)))
return -4009;
/* NIST decrypt test vector */
XMEMSET(buf, 0, sizeof(buf));
ret = wc_AesXtsDecrypt(&tweak, &aes, buf, c1, sizeof(c1), i1, sizeof(i1));
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE);
#endif
if (ret != 0)
return -4010;
if (XMEMCMP(p1, buf, AES_BLOCK_SIZE))
return -4011;
/* fail case with decrypting using wrong key */
XMEMSET(buf, 0, sizeof(buf));
ret = wc_AesXtsDecrypt(&tweak, &aes, buf, c2, sizeof(c2), i2, sizeof(i2));
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE);
#endif
if (ret != 0)
return -4012;
if (XMEMCMP(p2, buf, sizeof(p2)) == 0) /* fail case with wrong key */
return -4013;
/* set correct key and retest */
XMEMSET(buf, 0, sizeof(buf));
if (wc_AesXtsSetKey(&tweak, &aes, k2, sizeof(k2), AES_DECRYPTION,
HEAP_HINT, devId) != 0)
return -4014;
ret = wc_AesXtsDecrypt(&tweak, &aes, buf, c2, sizeof(c2), i2, sizeof(i2));
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE);
#endif
if (ret != 0)
return -4015;
if (XMEMCMP(p2, buf, sizeof(p2)))
return -4016;
wc_AesFree(&aes);
wc_AesFree(&tweak);
return ret;
}
static int aes_xts_256_test(void)
{
Aes aes;
Aes tweak;
int ret = 0;
unsigned char buf[AES_BLOCK_SIZE * 3];
unsigned char cipher[AES_BLOCK_SIZE * 3];
/* 256 key tests */
static unsigned char k1[] = {
0x1e, 0xa6, 0x61, 0xc5, 0x8d, 0x94, 0x3a, 0x0e,
0x48, 0x01, 0xe4, 0x2f, 0x4b, 0x09, 0x47, 0x14,
0x9e, 0x7f, 0x9f, 0x8e, 0x3e, 0x68, 0xd0, 0xc7,
0x50, 0x52, 0x10, 0xbd, 0x31, 0x1a, 0x0e, 0x7c,
0xd6, 0xe1, 0x3f, 0xfd, 0xf2, 0x41, 0x8d, 0x8d,
0x19, 0x11, 0xc0, 0x04, 0xcd, 0xa5, 0x8d, 0xa3,
0xd6, 0x19, 0xb7, 0xe2, 0xb9, 0x14, 0x1e, 0x58,
0x31, 0x8e, 0xea, 0x39, 0x2c, 0xf4, 0x1b, 0x08
};
static unsigned char i1[] = {
0xad, 0xf8, 0xd9, 0x26, 0x27, 0x46, 0x4a, 0xd2,
0xf0, 0x42, 0x8e, 0x84, 0xa9, 0xf8, 0x75, 0x64
};
static unsigned char p1[] = {
0x2e, 0xed, 0xea, 0x52, 0xcd, 0x82, 0x15, 0xe1,
0xac, 0xc6, 0x47, 0xe8, 0x10, 0xbb, 0xc3, 0x64,
0x2e, 0x87, 0x28, 0x7f, 0x8d, 0x2e, 0x57, 0xe3,
0x6c, 0x0a, 0x24, 0xfb, 0xc1, 0x2a, 0x20, 0x2e
};
/* plain text test of partial block is not from NIST test vector list */
static unsigned char pp[] = {
0xeb, 0xab, 0xce, 0x95, 0xb1, 0x4d, 0x3c, 0x8d,
0x6f, 0xb3, 0x50, 0x39, 0x07, 0x90, 0x31, 0x1c,
0x6e, 0x4b, 0x92, 0x01, 0x3e, 0x76, 0x8a, 0xd5
};
static unsigned char c1[] = {
0xcb, 0xaa, 0xd0, 0xe2, 0xf6, 0xce, 0xa3, 0xf5,
0x0b, 0x37, 0xf9, 0x34, 0xd4, 0x6a, 0x9b, 0x13,
0x0b, 0x9d, 0x54, 0xf0, 0x7e, 0x34, 0xf3, 0x6a,
0xf7, 0x93, 0xe8, 0x6f, 0x73, 0xc6, 0xd7, 0xdb
};
static unsigned char k2[] = {
0xad, 0x50, 0x4b, 0x85, 0xd7, 0x51, 0xbf, 0xba,
0x69, 0x13, 0xb4, 0xcc, 0x79, 0xb6, 0x5a, 0x62,
0xf7, 0xf3, 0x9d, 0x36, 0x0f, 0x35, 0xb5, 0xec,
0x4a, 0x7e, 0x95, 0xbd, 0x9b, 0xa5, 0xf2, 0xec,
0xc1, 0xd7, 0x7e, 0xa3, 0xc3, 0x74, 0xbd, 0x4b,
0x13, 0x1b, 0x07, 0x83, 0x87, 0xdd, 0x55, 0x5a,
0xb5, 0xb0, 0xc7, 0xe5, 0x2d, 0xb5, 0x06, 0x12,
0xd2, 0xb5, 0x3a, 0xcb, 0x47, 0x8a, 0x53, 0xb4
};
static unsigned char i2[] = {
0xe6, 0x42, 0x19, 0xed, 0xe0, 0xe1, 0xc2, 0xa0,
0x0e, 0xf5, 0x58, 0x6a, 0xc4, 0x9b, 0xeb, 0x6f
};
static unsigned char p2[] = {
0x24, 0xcb, 0x76, 0x22, 0x55, 0xb5, 0xa8, 0x00,
0xf4, 0x6e, 0x80, 0x60, 0x56, 0x9e, 0x05, 0x53,
0xbc, 0xfe, 0x86, 0x55, 0x3b, 0xca, 0xd5, 0x89,
0xc7, 0x54, 0x1a, 0x73, 0xac, 0xc3, 0x9a, 0xbd,
0x53, 0xc4, 0x07, 0x76, 0xd8, 0xe8, 0x22, 0x61,
0x9e, 0xa9, 0xad, 0x77, 0xa0, 0x13, 0x4c, 0xfc
};
static unsigned char c2[] = {
0xa3, 0xc6, 0xf3, 0xf3, 0x82, 0x79, 0x5b, 0x10,
0x87, 0xd7, 0x02, 0x50, 0xdb, 0x2c, 0xd3, 0xb1,
0xa1, 0x62, 0xa8, 0xb6, 0xdc, 0x12, 0x60, 0x61,
0xc1, 0x0a, 0x84, 0xa5, 0x85, 0x3f, 0x3a, 0x89,
0xe6, 0x6c, 0xdb, 0xb7, 0x9a, 0xb4, 0x28, 0x9b,
0xc3, 0xea, 0xd8, 0x10, 0xe9, 0xc0, 0xaf, 0x92
};
XMEMSET(buf, 0, sizeof(buf));
if (wc_AesXtsSetKey(&tweak, &aes, k2, sizeof(k2), AES_ENCRYPTION,
HEAP_HINT, devId) != 0)
return -4017;
ret = wc_AesXtsEncrypt(&tweak, &aes, buf, p2, sizeof(p2), i2, sizeof(i2));
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE);
#endif
if (ret != 0)
return -4018;
if (XMEMCMP(c2, buf, sizeof(c2)))
return -4019;
XMEMSET(buf, 0, sizeof(buf));
if (wc_AesXtsSetKey(&tweak, &aes, k1, sizeof(k1), AES_ENCRYPTION,
HEAP_HINT, devId) != 0)
return -4020;
ret = wc_AesXtsEncrypt(&tweak, &aes, buf, p1, sizeof(p1), i1, sizeof(i1));
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE);
#endif
if (ret != 0)
return -4021;
if (XMEMCMP(c1, buf, AES_BLOCK_SIZE))
return -4022;
/* partial block encryption test */
XMEMSET(cipher, 0, sizeof(cipher));
ret = wc_AesXtsEncrypt(&tweak, &aes, cipher, pp, sizeof(pp), i1, sizeof(i1));
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE);
#endif
if (ret != 0)
return -4023;
wc_AesFree(&aes);
wc_AesFree(&tweak);
/* partial block decrypt test */
XMEMSET(buf, 0, sizeof(buf));
if (wc_AesXtsSetKey(&tweak, &aes, k1, sizeof(k1), AES_DECRYPTION,
HEAP_HINT, devId) != 0)
return -4024;
ret = wc_AesXtsDecrypt(&tweak, &aes, buf, cipher, sizeof(pp), i1, sizeof(i1));
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE);
#endif
if (ret != 0)
return -4025;
if (XMEMCMP(pp, buf, sizeof(pp)))
return -4026;
/* NIST decrypt test vector */
XMEMSET(buf, 0, sizeof(buf));
ret = wc_AesXtsDecrypt(&tweak, &aes, buf, c1, sizeof(c1), i1, sizeof(i1));
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE);
#endif
if (ret != 0)
return -4027;
if (XMEMCMP(p1, buf, AES_BLOCK_SIZE))
return -4028;
XMEMSET(buf, 0, sizeof(buf));
if (wc_AesXtsSetKey(&tweak, &aes, k2, sizeof(k2), AES_DECRYPTION,
HEAP_HINT, devId) != 0)
return -4029;
ret = wc_AesXtsDecrypt(&tweak, &aes, buf, c2, sizeof(c2), i2, sizeof(i2));
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE);
#endif
if (ret != 0)
return -4030;
if (XMEMCMP(p2, buf, sizeof(p2)))
return -4031;
wc_AesFree(&aes);
wc_AesFree(&tweak);
return ret;
}
/* both 128 and 256 bit key test */
static int aes_xts_sector_test(void)
{
Aes aes;
Aes tweak;
int ret = 0;
unsigned char buf[AES_BLOCK_SIZE * 2];
/* 128 key tests */
static unsigned char k1[] = {
0xa3, 0xe4, 0x0d, 0x5b, 0xd4, 0xb6, 0xbb, 0xed,
0xb2, 0xd1, 0x8c, 0x70, 0x0a, 0xd2, 0xdb, 0x22,
0x10, 0xc8, 0x11, 0x90, 0x64, 0x6d, 0x67, 0x3c,
0xbc, 0xa5, 0x3f, 0x13, 0x3e, 0xab, 0x37, 0x3c
};
static unsigned char p1[] = {
0x20, 0xe0, 0x71, 0x94, 0x05, 0x99, 0x3f, 0x09,
0xa6, 0x6a, 0xe5, 0xbb, 0x50, 0x0e, 0x56, 0x2c
};
static unsigned char c1[] = {
0x74, 0x62, 0x35, 0x51, 0x21, 0x02, 0x16, 0xac,
0x92, 0x6b, 0x96, 0x50, 0xb6, 0xd3, 0xfa, 0x52
};
word64 s1 = 141;
/* 256 key tests */
static unsigned char k2[] = {
0xef, 0x01, 0x0c, 0xa1, 0xa3, 0x66, 0x3e, 0x32,
0x53, 0x43, 0x49, 0xbc, 0x0b, 0xae, 0x62, 0x23,
0x2a, 0x15, 0x73, 0x34, 0x85, 0x68, 0xfb, 0x9e,
0xf4, 0x17, 0x68, 0xa7, 0x67, 0x4f, 0x50, 0x7a,
0x72, 0x7f, 0x98, 0x75, 0x53, 0x97, 0xd0, 0xe0,
0xaa, 0x32, 0xf8, 0x30, 0x33, 0x8c, 0xc7, 0xa9,
0x26, 0xc7, 0x73, 0xf0, 0x9e, 0x57, 0xb3, 0x57,
0xcd, 0x15, 0x6a, 0xfb, 0xca, 0x46, 0xe1, 0xa0
};
static unsigned char p2[] = {
0xed, 0x98, 0xe0, 0x17, 0x70, 0xa8, 0x53, 0xb4,
0x9d, 0xb9, 0xe6, 0xaa, 0xf8, 0x8f, 0x0a, 0x41,
0xb9, 0xb5, 0x6e, 0x91, 0xa5, 0xa2, 0xb1, 0x1d,
0x40, 0x52, 0x92, 0x54, 0xf5, 0x52, 0x3e, 0x75
};
static unsigned char c2[] = {
0xca, 0x20, 0xc5, 0x5e, 0x8d, 0xc1, 0x49, 0x68,
0x7d, 0x25, 0x41, 0xde, 0x39, 0xc3, 0xdf, 0x63,
0x00, 0xbb, 0x5a, 0x16, 0x3c, 0x10, 0xce, 0xd3,
0x66, 0x6b, 0x13, 0x57, 0xdb, 0x8b, 0xd3, 0x9d
};
word64 s2 = 187;
XMEMSET(buf, 0, sizeof(buf));
if (wc_AesXtsSetKey(&tweak, &aes, k1, sizeof(k1), AES_ENCRYPTION,
HEAP_HINT, devId) != 0)
return -4032;
ret = wc_AesXtsEncryptSector(&tweak, &aes, buf, p1, sizeof(p1), s1);
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE);
#endif
if (ret != 0)
return -4033;
if (XMEMCMP(c1, buf, AES_BLOCK_SIZE))
return -4034;
/* decrypt test */
XMEMSET(buf, 0, sizeof(buf));
if (wc_AesXtsSetKey(&tweak, &aes, k1, sizeof(k1), AES_DECRYPTION,
HEAP_HINT, devId) != 0)
return -4035;
ret = wc_AesXtsDecryptSector(&tweak, &aes, buf, c1, sizeof(c1), s1);
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE);
#endif
if (ret != 0)
return -4036;
if (XMEMCMP(p1, buf, AES_BLOCK_SIZE))
return -4037;
wc_AesFree(&aes);
wc_AesFree(&tweak);
/* 256 bit key tests */
XMEMSET(buf, 0, sizeof(buf));
if (wc_AesXtsSetKey(&tweak, &aes, k2, sizeof(k2), AES_ENCRYPTION,
HEAP_HINT, devId) != 0)
return -4038;
ret = wc_AesXtsEncryptSector(&tweak, &aes, buf, p2, sizeof(p2), s2);
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE);
#endif
if (ret != 0)
return -4039;
if (XMEMCMP(c2, buf, sizeof(c2)))
return -4040;
/* decrypt test */
XMEMSET(buf, 0, sizeof(buf));
if (wc_AesXtsSetKey(&tweak, &aes, k2, sizeof(k2), AES_DECRYPTION,
HEAP_HINT, devId) != 0)
return -4041;
ret = wc_AesXtsDecryptSector(&tweak, &aes, buf, c2, sizeof(c2), s2);
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE);
#endif
if (ret != 0)
return -4042;
if (XMEMCMP(p2, buf, sizeof(p2)))
return -4043;
wc_AesFree(&aes);
wc_AesFree(&tweak);
return ret;
}
/* testing of bad arguments */
static int aes_xts_args_test(void)
{
Aes aes;
Aes tweak;
int ret = 0;
unsigned char buf[AES_BLOCK_SIZE * 2];
/* 128 key tests */
static unsigned char k1[] = {
0xa3, 0xe4, 0x0d, 0x5b, 0xd4, 0xb6, 0xbb, 0xed,
0xb2, 0xd1, 0x8c, 0x70, 0x0a, 0xd2, 0xdb, 0x22,
0x10, 0xc8, 0x11, 0x90, 0x64, 0x6d, 0x67, 0x3c,
0xbc, 0xa5, 0x3f, 0x13, 0x3e, 0xab, 0x37, 0x3c
};
static unsigned char p1[] = {
0x20, 0xe0, 0x71, 0x94, 0x05, 0x99, 0x3f, 0x09,
0xa6, 0x6a, 0xe5, 0xbb, 0x50, 0x0e, 0x56, 0x2c
};
static unsigned char c1[] = {
0x74, 0x62, 0x35, 0x51, 0x21, 0x02, 0x16, 0xac,
0x92, 0x6b, 0x96, 0x50, 0xb6, 0xd3, 0xfa, 0x52
};
word64 s1 = 141;
if (wc_AesXtsSetKey(NULL, &aes, k1, sizeof(k1), AES_ENCRYPTION,
HEAP_HINT, devId) == 0)
return -4044;
if (wc_AesXtsSetKey(&tweak, NULL, k1, sizeof(k1), AES_ENCRYPTION,
HEAP_HINT, devId) == 0)
return -4045;
if (wc_AesXtsSetKey(&tweak, &aes, NULL, sizeof(k1), AES_ENCRYPTION,
HEAP_HINT, devId) == 0)
return -4046;
/* set up wrong encrypt / decrypt types for key */
wc_AesSetKey(&aes, k1, sizeof(k1)/2, NULL, AES_DECRYPTION);
wc_AesSetKey(&tweak, k1 + sizeof(k1)/2, sizeof(k1)/2, NULL, AES_ENCRYPTION);
ret = wc_AesXtsEncryptSector(&tweak, &aes, buf, p1, sizeof(p1), s1);
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE);
#endif
if (ret == 0)
return -4047;
wc_AesFree(&aes);
wc_AesFree(&tweak);
/* tweak must be encryption type. Test with wrong decryption type used */
wc_AesSetKey(&aes, k1, sizeof(k1)/2, NULL, AES_ENCRYPTION);
wc_AesSetKey(&tweak, k1 + sizeof(k1)/2, sizeof(k1)/2, NULL, AES_DECRYPTION);
ret = wc_AesXtsEncryptSector(&tweak, &aes, buf, p1, sizeof(p1), s1);
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE);
#endif
if (ret == 0)
return -4048;
wc_AesFree(&aes);
wc_AesFree(&tweak);
/* Test for fail with encryption key used for decryption */
if (wc_AesXtsSetKey(&tweak, &aes, k1, sizeof(k1), AES_ENCRYPTION,
HEAP_HINT, devId) != 0)
return -4049;
ret = wc_AesXtsDecryptSector(&tweak, &aes, buf, c1, sizeof(c1), s1);
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE);
#endif
if (ret == 0)
return -4050;
wc_AesFree(&aes);
wc_AesFree(&tweak);
return 0;
}
#endif /* WOLFSSL_AES_XTS */
#if defined(HAVE_AES_CBC)
static int aes_cbc_test(void)
{
@@ -4647,6 +5162,21 @@ int aes_test(void)
return ret;
#endif
#if defined(WOLFSSL_AES_XTS)
ret = aes_xts_128_test();
if (ret != 0)
return ret;
ret = aes_xts_256_test();
if (ret != 0)
return ret;
ret = aes_xts_sector_test();
if (ret != 0)
return ret;
ret = aes_xts_args_test();
if (ret != 0)
return ret;
#endif
wc_AesFree(&enc);
#ifdef HAVE_AES_DECRYPT
wc_AesFree(&dec);

View File

@@ -109,6 +109,10 @@ typedef struct Aes {
XCsuDma dma;
word32 key_init[8];
word32 kup;
#endif
#ifdef WOLFSSL_AES_XTS
byte type; /* adds the ability to do a sanity check on key for
* encrypt/decrypt */
#endif
void* heap; /* memory hint to use */
} Aes;
@@ -210,6 +214,19 @@ WOLFSSL_API int wc_AesEcbDecrypt(Aes* aes, byte* out,
const byte* iv);
#endif /* HAVE_AES_KEYWRAP */
#ifdef WOLFSSL_AES_XTS
WOLFSSL_API int wc_AesXtsSetKey(Aes* tweak, Aes* aes, const byte* key,
word32 len, int dir, void* heap, int devId);
WOLFSSL_API int wc_AesXtsEncryptSector(Aes* tweak, Aes* aes, byte* out,
const byte* in, word32 sz, word64 sector);
WOLFSSL_API int wc_AesXtsDecryptSector(Aes* tweak, Aes* aes, byte* out,
const byte* in, word32 sz, word64 sector);
WOLFSSL_API int wc_AesXtsEncrypt(Aes* tweak, Aes* aes, byte* out,
const byte* in, word32 sz, const byte* i, word32 iSz);
WOLFSSL_API int wc_AesXtsDecrypt(Aes* tweak, Aes* aes, byte* out,
const byte* in, word32 sz, const byte* i, word32 iSz);
#endif
WOLFSSL_API int wc_AesGetKeySize(Aes* aes, word32* keySize);
WOLFSSL_API int wc_AesInit(Aes*, void*, int);

View File

@@ -1344,6 +1344,12 @@ extern void uITRON4_free(void *p) ;
#error "AES CBC is required for TLS and can only be disabled for WOLFCRYPT_ONLY builds"
#endif
#endif
#ifdef WOLFSSL_AES_XTS
/* AES-XTS makes calls to AES direct functions */
#ifndef WOLFSSL_AES_DIRECT
#define WOLFSSL_AES_DIRECT
#endif
#endif
#endif
/* if desktop type system and fastmath increase default max bits */