diff --git a/configure.ac b/configure.ac index 0f9606038..9a3ca0088 100644 --- a/configure.ac +++ b/configure.ac @@ -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)])], diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index 3c6d831e9..2de5c16a0 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -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,71 @@ exit: #endif /* HAVE_AESGCM */ +#ifdef WOLFSSL_AES_XTS +void bench_aesxts(void) +{ + XtsAes aes; + 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(&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(&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_AesXtsFree(&aes); + + /* decryption benchmark */ + ret = wc_AesXtsSetKey(&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(&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_AesXtsFree(&aes); +} +#endif /* WOLFSSL_AES_XTS */ + + #ifdef WOLFSSL_AES_COUNTER void bench_aesctr(void) { diff --git a/wolfcrypt/benchmark/benchmark.h b/wolfcrypt/benchmark/benchmark.h index 8f1615bc9..7fc7b31f0 100644 --- a/wolfcrypt/benchmark/benchmark.h +++ b/wolfcrypt/benchmark/benchmark.h @@ -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); diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index c59fa616d..8175083bc 100755 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -8010,5 +8010,354 @@ 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(XtsAes* aes, const byte* key, word32 len, int dir, + void* heap, int devId) +{ + word32 keySz; + int ret = 0; + + if (aes == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + + if ((ret = wc_AesInit(&aes->tweak, heap, devId)) != 0) { + return ret; + } + if ((ret = wc_AesInit(&aes->aes, heap, devId)) != 0) { + return ret; + } + + keySz = len/2; + if (keySz != 16 && keySz != 32) { + WOLFSSL_MSG("Unsupported key size"); + return WC_KEY_SIZE_E; + } + + if ((ret = wc_AesSetKey(&aes->aes, key, keySz, NULL, dir)) == 0) { + ret = wc_AesSetKey(&aes->tweak, key + keySz, keySz, NULL, + AES_ENCRYPTION); + if (ret != 0) { + wc_AesFree(&aes->aes); + } + } + + return ret; +} + + +/* This is used to free up resources used by Aes structs + * + * aes AES keys to free + * + * return 0 on success + */ +int wc_AesXtsFree(XtsAes* aes) +{ + if (aes != NULL) { + wc_AesFree(&aes->aes); + wc_AesFree(&aes->tweak); + } + + return 0; +} + + +/* 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. + * + * aes AES keys 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(XtsAes* aes, byte* out, const byte* in, + word32 sz, word64 sector) +{ + byte* pt; + byte i[AES_BLOCK_SIZE]; + + XMEMSET(i, 0, AES_BLOCK_SIZE); +#ifdef BIG_ENDIAN_ORDER + sector = ByteReverseWord64(sector); +#endif + pt = (byte*)§or; + XMEMCPY(i, pt, sizeof(word64)); + + return wc_AesXtsEncrypt(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. + * + * aes AES keys 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(XtsAes* aes, byte* out, const byte* in, word32 sz, + word64 sector) +{ + byte* pt; + byte i[AES_BLOCK_SIZE]; + + XMEMSET(i, 0, AES_BLOCK_SIZE); +#ifdef BIG_ENDIAN_ORDER + sector = ByteReverseWord64(sector); +#endif + pt = (byte*)§or; + XMEMCPY(i, pt, sizeof(word64)); + + return wc_AesXtsDecrypt(aes, out, in, sz, (const byte*)i, AES_BLOCK_SIZE); +} + + +/* AES with XTS mode. (XTS) XEX encryption with Tweak and cipher text Stealing. + * + * xaes AES keys 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(XtsAes* xaes, byte* out, const byte* in, word32 sz, + const byte* i, word32 iSz) +{ + int ret = 0; + word32 blocks = (sz / AES_BLOCK_SIZE); + Aes *aes, *tweak; + + if (xaes == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + + aes = &xaes->aes; + tweak = &xaes->tweak; + + 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. + * + * xaes AES keys 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(XtsAes* xaes, byte* out, const byte* in, word32 sz, + const byte* i, word32 iSz) +{ + int ret = 0; + word32 blocks = (sz / AES_BLOCK_SIZE); + Aes *aes, *tweak; + + if (xaes == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + + aes = &xaes->aes; + tweak = &xaes->tweak; + + 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 */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index b43295ab2..2a983c90c 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -4202,6 +4202,509 @@ 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) +{ + XtsAes aes; + 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(&aes, k2, sizeof(k2), AES_ENCRYPTION, + HEAP_HINT, devId) != 0) + return -4000; + ret = wc_AesXtsEncrypt(&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(&aes, k1, sizeof(k1), AES_ENCRYPTION, + HEAP_HINT, devId) != 0) + return -4003; + ret = wc_AesXtsEncrypt(&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(&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_AesXtsFree(&aes); + + /* partial block decrypt test */ + XMEMSET(buf, 0, sizeof(buf)); + if (wc_AesXtsSetKey(&aes, k1, sizeof(k1), AES_DECRYPTION, + HEAP_HINT, devId) != 0) + return -4007; + ret = wc_AesXtsDecrypt(&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(&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(&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(&aes, k2, sizeof(k2), AES_DECRYPTION, + HEAP_HINT, devId) != 0) + return -4014; + ret = wc_AesXtsDecrypt(&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_AesXtsFree(&aes); + + return ret; +} + + +static int aes_xts_256_test(void) +{ + XtsAes aes; + 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(&aes, k2, sizeof(k2), AES_ENCRYPTION, + HEAP_HINT, devId) != 0) + return -4017; + ret = wc_AesXtsEncrypt(&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(&aes, k1, sizeof(k1), AES_ENCRYPTION, + HEAP_HINT, devId) != 0) + return -4020; + ret = wc_AesXtsEncrypt(&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(&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_AesXtsFree(&aes); + + /* partial block decrypt test */ + XMEMSET(buf, 0, sizeof(buf)); + if (wc_AesXtsSetKey(&aes, k1, sizeof(k1), AES_DECRYPTION, + HEAP_HINT, devId) != 0) + return -4024; + ret = wc_AesXtsDecrypt(&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(&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(&aes, k2, sizeof(k2), AES_DECRYPTION, + HEAP_HINT, devId) != 0) + return -4029; + ret = wc_AesXtsDecrypt(&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_AesXtsFree(&aes); + + return ret; +} + + +/* both 128 and 256 bit key test */ +static int aes_xts_sector_test(void) +{ + XtsAes aes; + 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(&aes, k1, sizeof(k1), AES_ENCRYPTION, + HEAP_HINT, devId) != 0) + return -4032; + ret = wc_AesXtsEncryptSector(&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(&aes, k1, sizeof(k1), AES_DECRYPTION, + HEAP_HINT, devId) != 0) + return -4035; + ret = wc_AesXtsDecryptSector(&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_AesXtsFree(&aes); + + /* 256 bit key tests */ + XMEMSET(buf, 0, sizeof(buf)); + if (wc_AesXtsSetKey(&aes, k2, sizeof(k2), AES_ENCRYPTION, + HEAP_HINT, devId) != 0) + return -4038; + ret = wc_AesXtsEncryptSector(&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(&aes, k2, sizeof(k2), AES_DECRYPTION, + HEAP_HINT, devId) != 0) + return -4041; + ret = wc_AesXtsDecryptSector(&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_AesXtsFree(&aes); + + return ret; +} + + +/* testing of bad arguments */ +static int aes_xts_args_test(void) +{ + XtsAes aes; + 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, k1, sizeof(k1), AES_ENCRYPTION, + HEAP_HINT, devId) == 0) + return -4044; + if (wc_AesXtsSetKey(&aes, NULL, sizeof(k1), AES_ENCRYPTION, + HEAP_HINT, devId) == 0) + return -4045; + + /* encryption operations */ + if (wc_AesXtsSetKey(&aes, k1, sizeof(k1), AES_ENCRYPTION, + HEAP_HINT, devId) != 0) + return -4046; + ret = wc_AesXtsEncryptSector(NULL, 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; + + ret = wc_AesXtsEncryptSector(&aes, NULL, 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_AesXtsFree(&aes); + + /* decryption operations */ + if (wc_AesXtsSetKey(&aes, k1, sizeof(k1), AES_DECRYPTION, + HEAP_HINT, devId) != 0) + return -4046; + ret = wc_AesXtsDecryptSector(NULL, 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 -4049; + + ret = wc_AesXtsDecryptSector(&aes, NULL, 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_AesXtsFree(&aes); + + return 0; +} +#endif /* WOLFSSL_AES_XTS */ + #if defined(HAVE_AES_CBC) static int aes_cbc_test(void) { @@ -4647,6 +5150,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); diff --git a/wolfssl/wolfcrypt/aes.h b/wolfssl/wolfcrypt/aes.h index aa5fb9465..587432341 100755 --- a/wolfssl/wolfcrypt/aes.h +++ b/wolfssl/wolfcrypt/aes.h @@ -113,6 +113,12 @@ typedef struct Aes { void* heap; /* memory hint to use */ } Aes; +#ifdef WOLFSSL_AES_XTS +typedef struct XtsAes { + Aes aes; + Aes tweak; +} XtsAes; +#endif #ifdef HAVE_AESGCM typedef struct Gmac { @@ -210,6 +216,230 @@ WOLFSSL_API int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* iv); #endif /* HAVE_AES_KEYWRAP */ +#ifdef WOLFSSL_AES_XTS +/*! + \ingroup AES + + \brief This is to help with setting keys to correct encrypt or decrypt type. + + \note Is up to user to call wc_AesXtsFree on aes key when done. + + \return 0 Success + + \param aes AES keys for encrypt/decrypt process + \param key buffer holding aes key | tweak key + \param len length of key buffer in bytes. Should be twice that of key size. + i.e. 32 for a 16 byte key. + \param dir direction, either AES_ENCRYPTION or AES_DECRYPTION + \param heap heap hint to use for memory. Can be NULL + \param devId id to use with async crypto. Can be 0 + + _Example_ + \code + XtsAes aes; + + if(wc_AesXtsSetKey(&aes, key, sizeof(key), AES_ENCRYPTION, NULL, 0) != 0) + { + // Handle error + } + wc_AesXtsFree(&aes); + \endcode + + \sa wc_AesXtsEncrypt + \sa wc_AesXtsDecrypt + \sa wc_AesXtsFree +*/ +WOLFSSL_API int wc_AesXtsSetKey(XtsAes* aes, const byte* key, + word32 len, int dir, void* heap, int devId); + + +/*! + \ingroup AES + + \brief 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. + + \return 0 Success + + \param aes AES keys to use for block encrypt/decrypt + \param out output buffer to hold cipher text + \param in input plain text buffer to encrypt + \param sz size of both out and in buffers + \param sector value to use for tweak + + _Example_ + \code + XtsAes aes; + unsigned char plain[SIZE]; + unsigned char cipher[SIZE]; + word64 s = VALUE; + + //set up keys with AES_ENCRYPTION as dir + + if(wc_AesXtsEncryptSector(&aes, cipher, plain, SIZE, s) != 0) + { + // Handle error + } + wc_AesXtsFree(&aes); + \endcode + + \sa wc_AesXtsEncrypt + \sa wc_AesXtsDecrypt + \sa wc_AesXtsSetKey + \sa wc_AesXtsFree +*/ +WOLFSSL_API int wc_AesXtsEncryptSector(XtsAes* aes, byte* out, + const byte* in, word32 sz, word64 sector); + + +/*! + \ingroup AES + + \brief 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. + + \return 0 Success + + \param aes AES keys to use for block encrypt/decrypt + \param out output buffer to hold plain text + \param in input cipher text buffer to decrypt + \param sz size of both out and in buffers + \param sector value to use for tweak + + _Example_ + \code + XtsAes aes; + unsigned char plain[SIZE]; + unsigned char cipher[SIZE]; + word64 s = VALUE; + + //set up aes key with AES_DECRYPTION as dir and tweak with AES_ENCRYPTION + + if(wc_AesXtsDecryptSector(&aes, plain, cipher, SIZE, s) != 0) + { + // Handle error + } + wc_AesXtsFree(&aes); + \endcode + + \sa wc_AesXtsEncrypt + \sa wc_AesXtsDecrypt + \sa wc_AesXtsSetKey + \sa wc_AesXtsFree +*/ +WOLFSSL_API int wc_AesXtsDecryptSector(XtsAes* aes, byte* out, + const byte* in, word32 sz, word64 sector); + + +/*! + \ingroup AES + + \brief AES with XTS mode. (XTS) XEX encryption with Tweak and cipher text + Stealing. + + \return 0 Success + + \param aes AES keys to use for block encrypt/decrypt + \param out output buffer to hold cipher text + \param in input plain text buffer to encrypt + \param sz size of both out and in buffers + \param i value to use for tweak + \param 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. + + _Example_ + \code + XtsAes aes; + unsigned char plain[SIZE]; + unsigned char cipher[SIZE]; + unsigned char i[AES_BLOCK_SIZE]; + + //set up key with AES_ENCRYPTION as dir + + if(wc_AesXtsEncrypt(&aes, cipher, plain, SIZE, i, sizeof(i)) != 0) + { + // Handle error + } + wc_AesXtsFree(&aes); + \endcode + + \sa wc_AesXtsDecrypt + \sa wc_AesXtsSetKey + \sa wc_AesXtsFree +*/ +WOLFSSL_API int wc_AesXtsEncrypt(XtsAes* aes, byte* out, + const byte* in, word32 sz, const byte* i, word32 iSz); + + +/*! + \ingroup AES + + \brief Same process as encryption but Aes key is AES_DECRYPTION type. + + \return 0 Success + + \param aes AES keys to use for block encrypt/decrypt + \param out output buffer to hold plain text + \param in input cipher text buffer to decrypt + \param sz size of both out and in buffers + \param i value to use for tweak + \param 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. + _Example_ + \code + XtsAes aes; + unsigned char plain[SIZE]; + unsigned char cipher[SIZE]; + unsigned char i[AES_BLOCK_SIZE]; + + //set up key with AES_DECRYPTION as dir and tweak with AES_ENCRYPTION + + if(wc_AesXtsDecrypt(&aes, plain, cipher, SIZE, i, sizeof(i)) != 0) + { + // Handle error + } + wc_AesXtsFree(&aes); + \endcode + + \sa wc_AesXtsEncrypt + \sa wc_AesXtsSetKey + \sa wc_AesXtsFree +*/ +WOLFSSL_API int wc_AesXtsDecrypt(XtsAes* aes, byte* out, + const byte* in, word32 sz, const byte* i, word32 iSz); + + +/*! + \ingroup AES + + \brief This is to free up any resources used by the XtsAes structure + + \return 0 Success + + \param aes AES keys to free + + _Example_ + \code + XtsAes aes; + + if(wc_AesXtsSetKey(&aes, key, sizeof(key), AES_ENCRYPTION, NULL, 0) != 0) + { + // Handle error + } + wc_AesXtsFree(&aes); + \endcode + + \sa wc_AesXtsEncrypt + \sa wc_AesXtsDecrypt + \sa wc_AesXtsSetKey +*/ +WOLFSSL_API int wc_AesXtsFree(XtsAes* aes); +#endif + WOLFSSL_API int wc_AesGetKeySize(Aes* aes, word32* keySize); WOLFSSL_API int wc_AesInit(Aes*, void*, int); diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index c3c9e513f..6fba5a8a4 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -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 */