forked from wolfSSL/wolfssl
AES-XTS:
split XtsAes.aes in two, XtsAes.aes_encrypt and XtsAes.aes_decrypt, and add AES_ENCRYPTION_AND_DECRYPTION option constant, to accommodate Linux kernel crypto API model. in wc_AesXtsSetKeyNoInit(), add FIPS check that main and tweak keys differ, and allow setting encrypt and decrypt keys simultaneously using AES_ENCRYPTION_AND_DECRYPTION. in wc_AesXtsEncrypt() and wc_AesXtsDecrypt(), error if the required subkey has not been set.
This commit is contained in:
@ -6383,7 +6383,6 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
|
|||||||
#endif
|
#endif
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef OPENSSL_EXTRA
|
#ifdef OPENSSL_EXTRA
|
||||||
XMEMSET(aes->gcm.aadH, 0, sizeof(aes->gcm.aadH));
|
XMEMSET(aes->gcm.aadH, 0, sizeof(aes->gcm.aadH));
|
||||||
aes->gcm.aadLen = 0;
|
aes->gcm.aadLen = 0;
|
||||||
@ -12250,7 +12249,7 @@ int wc_AesKeyUnWrap(const byte* key, word32 keySz, const byte* in, word32 inSz,
|
|||||||
|
|
||||||
#ifdef WOLFSSL_AES_XTS
|
#ifdef WOLFSSL_AES_XTS
|
||||||
|
|
||||||
/* Galios Field to use */
|
/* Galois Field to use */
|
||||||
#define GF_XTS 0x87
|
#define GF_XTS 0x87
|
||||||
|
|
||||||
int wc_AesXtsInit(XtsAes* aes, void* heap, int devId)
|
int wc_AesXtsInit(XtsAes* aes, void* heap, int devId)
|
||||||
@ -12264,21 +12263,28 @@ int wc_AesXtsInit(XtsAes* aes, void* heap, int devId)
|
|||||||
if ((ret = wc_AesInit(&aes->tweak, heap, devId)) != 0) {
|
if ((ret = wc_AesInit(&aes->tweak, heap, devId)) != 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if ((ret = wc_AesInit(&aes->aes, heap, devId)) != 0) {
|
if ((ret = wc_AesInit(&aes->aes_encrypt, heap, devId)) != 0) {
|
||||||
|
(void)wc_AesFree(&aes->tweak);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if ((ret = wc_AesInit(&aes->aes_decrypt, heap, devId)) != 0) {
|
||||||
|
(void)wc_AesFree(&aes->tweak);
|
||||||
|
(void)wc_AesFree(&aes->aes_encrypt);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is to help with setting keys to correct encrypt or decrypt type.
|
/* Set up keys for encryption and/or decryption.
|
||||||
*
|
*
|
||||||
* tweak AES key for tweak in XTS
|
* tweak AES key for tweak in XTS
|
||||||
* aes AES key for encrypt/decrypt process
|
* aes AES key for encrypt/decrypt process
|
||||||
* key buffer holding aes key | tweak key
|
* key buffer holding aes key | tweak key
|
||||||
* len length of key buffer in bytes. Should be twice that of key size. i.e.
|
* len length of key buffer in bytes. Should be twice that of key size. i.e.
|
||||||
* 32 for a 16 byte key.
|
* 32 for a 16 byte key.
|
||||||
* dir direction, either AES_ENCRYPTION or AES_DECRYPTION
|
* dir direction: AES_ENCRYPTION, AES_DECRYPTION, or
|
||||||
|
* AES_ENCRYPTION_AND_DECRYPTION
|
||||||
* heap heap hint to use for memory. Can be NULL
|
* heap heap hint to use for memory. Can be NULL
|
||||||
* devId id to use with async crypto. Can be 0
|
* devId id to use with async crypto. Can be 0
|
||||||
*
|
*
|
||||||
@ -12294,26 +12300,49 @@ int wc_AesXtsSetKeyNoInit(XtsAes* aes, const byte* key, word32 len, int dir)
|
|||||||
}
|
}
|
||||||
|
|
||||||
keySz = len/2;
|
keySz = len/2;
|
||||||
if (keySz != 16 && keySz != 32) {
|
if (keySz != AES_128_KEY_SIZE && keySz != AES_256_KEY_SIZE) {
|
||||||
WOLFSSL_MSG("Unsupported key size");
|
WOLFSSL_MSG("Unsupported key size");
|
||||||
return WC_KEY_SIZE_E;
|
return WC_KEY_SIZE_E;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = wc_AesSetKey(&aes->aes, key, keySz, NULL, dir)) == 0) {
|
#ifdef HAVE_FIPS_VERSION
|
||||||
|
if (XMEMCMP(key, key + keySz, keySz) == 0) {
|
||||||
|
WOLFSSL_MSG("FIPS AES-XTS main and tweak keys must differ");
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((dir == AES_ENCRYPTION) || (dir == AES_ENCRYPTION_AND_DECRYPTION))
|
||||||
|
ret = wc_AesSetKey(&aes->aes_encrypt, key, keySz, NULL, AES_ENCRYPTION);
|
||||||
|
|
||||||
|
if ((ret == 0) && ((dir == AES_DECRYPTION) || (dir == AES_ENCRYPTION_AND_DECRYPTION)))
|
||||||
|
ret = wc_AesSetKey(&aes->aes_decrypt, key, keySz, NULL, AES_DECRYPTION);
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
ret = wc_AesSetKey(&aes->tweak, key + keySz, keySz, NULL,
|
ret = wc_AesSetKey(&aes->tweak, key + keySz, keySz, NULL,
|
||||||
AES_ENCRYPTION);
|
AES_ENCRYPTION);
|
||||||
if (ret != 0) {
|
|
||||||
wc_AesFree(&aes->aes);
|
|
||||||
}
|
|
||||||
#ifdef WOLFSSL_AESNI
|
#ifdef WOLFSSL_AESNI
|
||||||
if (aes->aes.use_aesni != aes->tweak.use_aesni) {
|
if (ret == 0) {
|
||||||
if (aes->aes.use_aesni)
|
/* With WC_AES_C_DYNAMIC_FALLBACK, the main and tweak keys could have
|
||||||
aes->aes.use_aesni = 0;
|
* conflicting _aesni status, but the AES-XTS asm implementations need
|
||||||
else
|
* them to all be AESNI. If any aren't, disable AESNI on all.
|
||||||
aes->tweak.use_aesni = 0;
|
*/
|
||||||
}
|
if ((((dir == AES_ENCRYPTION) || (dir == AES_ENCRYPTION_AND_DECRYPTION)) &&
|
||||||
|
(aes->aes_encrypt.use_aesni != aes->tweak.use_aesni)) ||
|
||||||
|
(((dir == AES_DECRYPTION) || (dir == AES_ENCRYPTION_AND_DECRYPTION)) &&
|
||||||
|
(aes->aes_decrypt.use_aesni != aes->tweak.use_aesni)))
|
||||||
|
{
|
||||||
|
#ifdef WC_AES_C_DYNAMIC_FALLBACK
|
||||||
|
aes->aes_encrypt.use_aesni = 0;
|
||||||
|
aes->aes_decrypt.use_aesni = 0;
|
||||||
|
aes->tweak.use_aesni = 0;
|
||||||
|
#else
|
||||||
|
ret = SYSLIB_FAILED_E;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -12355,7 +12384,8 @@ int wc_AesXtsSetKey(XtsAes* aes, const byte* key, word32 len, int dir,
|
|||||||
int wc_AesXtsFree(XtsAes* aes)
|
int wc_AesXtsFree(XtsAes* aes)
|
||||||
{
|
{
|
||||||
if (aes != NULL) {
|
if (aes != NULL) {
|
||||||
wc_AesFree(&aes->aes);
|
wc_AesFree(&aes->aes_encrypt);
|
||||||
|
wc_AesFree(&aes->aes_decrypt);
|
||||||
wc_AesFree(&aes->tweak);
|
wc_AesFree(&aes->tweak);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12512,7 +12542,7 @@ static int AesXtsEncrypt_sw(XtsAes* xaes, byte* out, const byte* in, word32 sz,
|
|||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
word32 blocks = (sz / AES_BLOCK_SIZE);
|
word32 blocks = (sz / AES_BLOCK_SIZE);
|
||||||
Aes *aes = &xaes->aes;
|
Aes *aes = &xaes->aes_encrypt;
|
||||||
Aes *tweak = &xaes->tweak;
|
Aes *tweak = &xaes->tweak;
|
||||||
byte tmp[AES_BLOCK_SIZE];
|
byte tmp[AES_BLOCK_SIZE];
|
||||||
|
|
||||||
@ -12619,6 +12649,11 @@ int wc_AesXtsEncrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz,
|
|||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (xaes->aes_encrypt.keylen == 0) {
|
||||||
|
WOLFSSL_MSG("wc_AesXtsEncrypt called with unset encryption key.");
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
if (iSz < AES_BLOCK_SIZE) {
|
if (iSz < AES_BLOCK_SIZE) {
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
}
|
}
|
||||||
@ -12631,28 +12666,29 @@ int wc_AesXtsEncrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz,
|
|||||||
{
|
{
|
||||||
#ifdef WOLFSSL_AESNI
|
#ifdef WOLFSSL_AESNI
|
||||||
#ifdef WC_AES_C_DYNAMIC_FALLBACK
|
#ifdef WC_AES_C_DYNAMIC_FALLBACK
|
||||||
int orig_use_aesni = xaes->aes.use_aesni;
|
int orig_use_aesni = xaes->aes_encrypt.use_aesni;
|
||||||
#endif
|
#endif
|
||||||
if (xaes->aes.use_aesni && ((ret = SAVE_VECTOR_REGISTERS2()) != 0)) {
|
|
||||||
|
if (xaes->aes_encrypt.use_aesni && ((ret = SAVE_VECTOR_REGISTERS2()) != 0)) {
|
||||||
#ifdef WC_AES_C_DYNAMIC_FALLBACK
|
#ifdef WC_AES_C_DYNAMIC_FALLBACK
|
||||||
xaes->aes.use_aesni = 0;
|
xaes->aes_encrypt.use_aesni = 0;
|
||||||
xaes->tweak.use_aesni = 0;
|
xaes->tweak.use_aesni = 0;
|
||||||
#else
|
#else
|
||||||
return ret;
|
return ret;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (xaes->aes.use_aesni) {
|
if (xaes->aes_encrypt.use_aesni) {
|
||||||
#if defined(HAVE_INTEL_AVX1)
|
#if defined(HAVE_INTEL_AVX1)
|
||||||
if (IS_INTEL_AVX1(intel_flags)) {
|
if (IS_INTEL_AVX1(intel_flags)) {
|
||||||
AES_XTS_encrypt_avx1(in, out, sz, i, (const byte*)xaes->aes.key,
|
AES_XTS_encrypt_avx1(in, out, sz, i, (const byte*)xaes->aes_encrypt.key,
|
||||||
(const byte*)xaes->tweak.key, (int)xaes->aes.rounds);
|
(const byte*)xaes->tweak.key, (int)xaes->aes_encrypt.rounds);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
AES_XTS_encrypt_aesni(in, out, sz, i, (const byte*)xaes->aes.key,
|
AES_XTS_encrypt_aesni(in, out, sz, i, (const byte*)xaes->aes_encrypt.key,
|
||||||
(const byte*)xaes->tweak.key, (int)xaes->aes.rounds);
|
(const byte*)xaes->tweak.key, (int)xaes->aes_encrypt.rounds);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -12663,11 +12699,11 @@ int wc_AesXtsEncrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WOLFSSL_AESNI
|
#ifdef WOLFSSL_AESNI
|
||||||
if (xaes->aes.use_aesni)
|
if (xaes->aes_encrypt.use_aesni)
|
||||||
RESTORE_VECTOR_REGISTERS();
|
RESTORE_VECTOR_REGISTERS();
|
||||||
#ifdef WC_AES_C_DYNAMIC_FALLBACK
|
#ifdef WC_AES_C_DYNAMIC_FALLBACK
|
||||||
else if (orig_use_aesni) {
|
else if (orig_use_aesni) {
|
||||||
xaes->aes.use_aesni = orig_use_aesni;
|
xaes->aes_encrypt.use_aesni = orig_use_aesni;
|
||||||
xaes->tweak.use_aesni = orig_use_aesni;
|
xaes->tweak.use_aesni = orig_use_aesni;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -12677,7 +12713,7 @@ int wc_AesXtsEncrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Same process as encryption but Aes key is AES_DECRYPTION type.
|
/* Same process as encryption but use aes_decrypt key.
|
||||||
*
|
*
|
||||||
* xaes AES keys to use for block encrypt/decrypt
|
* xaes AES keys to use for block encrypt/decrypt
|
||||||
* out output buffer to hold plain text
|
* out output buffer to hold plain text
|
||||||
@ -12693,7 +12729,7 @@ static int AesXtsDecrypt_sw(XtsAes* xaes, byte* out, const byte* in, word32 sz,
|
|||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
word32 blocks = (sz / AES_BLOCK_SIZE);
|
word32 blocks = (sz / AES_BLOCK_SIZE);
|
||||||
Aes *aes = &xaes->aes;
|
Aes *aes = &xaes->aes_decrypt;
|
||||||
Aes *tweak = &xaes->tweak;
|
Aes *tweak = &xaes->tweak;
|
||||||
word32 j;
|
word32 j;
|
||||||
byte carry = 0;
|
byte carry = 0;
|
||||||
@ -12826,6 +12862,11 @@ int wc_AesXtsDecrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz,
|
|||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (xaes->aes_decrypt.keylen == 0) {
|
||||||
|
WOLFSSL_MSG("wc_AesXtsDecrypt called with unset decryption key.");
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
if (iSz < AES_BLOCK_SIZE) {
|
if (iSz < AES_BLOCK_SIZE) {
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
}
|
}
|
||||||
@ -12838,25 +12879,29 @@ int wc_AesXtsDecrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz,
|
|||||||
{
|
{
|
||||||
#ifdef WOLFSSL_AESNI
|
#ifdef WOLFSSL_AESNI
|
||||||
#ifdef WC_AES_C_DYNAMIC_FALLBACK
|
#ifdef WC_AES_C_DYNAMIC_FALLBACK
|
||||||
int orig_use_aesni = xaes->aes.use_aesni;
|
int orig_use_aesni = xaes->aes_decrypt.use_aesni;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (xaes->aes.use_aesni && (SAVE_VECTOR_REGISTERS2() != 0)) {
|
if (xaes->aes_decrypt.use_aesni && ((ret = SAVE_VECTOR_REGISTERS2() != 0))) {
|
||||||
xaes->aes.use_aesni = 0;
|
#ifdef WC_AES_C_DYNAMIC_FALLBACK
|
||||||
|
xaes->aes_decrypt.use_aesni = 0;
|
||||||
xaes->tweak.use_aesni = 0;
|
xaes->tweak.use_aesni = 0;
|
||||||
|
#else
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if (xaes->aes.use_aesni) {
|
if (xaes->aes_decrypt.use_aesni) {
|
||||||
#if defined(HAVE_INTEL_AVX1)
|
#if defined(HAVE_INTEL_AVX1)
|
||||||
if (IS_INTEL_AVX1(intel_flags)) {
|
if (IS_INTEL_AVX1(intel_flags)) {
|
||||||
AES_XTS_decrypt_avx1(in, out, sz, i, (const byte*)xaes->aes.key,
|
AES_XTS_decrypt_avx1(in, out, sz, i, (const byte*)xaes->aes_decrypt.key,
|
||||||
(const byte*)xaes->tweak.key, (int)xaes->aes.rounds);
|
(const byte*)xaes->tweak.key, (int)xaes->aes_decrypt.rounds);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
AES_XTS_decrypt_aesni(in, out, sz, i, (const byte*)xaes->aes.key,
|
AES_XTS_decrypt_aesni(in, out, sz, i, (const byte*)xaes->aes_decrypt.key,
|
||||||
(const byte*)xaes->tweak.key, (int)xaes->aes.rounds);
|
(const byte*)xaes->tweak.key, (int)xaes->aes_decrypt.rounds);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -12867,11 +12912,11 @@ int wc_AesXtsDecrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WOLFSSL_AESNI
|
#ifdef WOLFSSL_AESNI
|
||||||
if (xaes->aes.use_aesni)
|
if (xaes->aes_decrypt.use_aesni)
|
||||||
RESTORE_VECTOR_REGISTERS();
|
RESTORE_VECTOR_REGISTERS();
|
||||||
#ifdef WC_AES_C_DYNAMIC_FALLBACK
|
#ifdef WC_AES_C_DYNAMIC_FALLBACK
|
||||||
else if (orig_use_aesni) {
|
else if (orig_use_aesni) {
|
||||||
xaes->aes.use_aesni = orig_use_aesni;
|
xaes->aes_decrypt.use_aesni = orig_use_aesni;
|
||||||
xaes->tweak.use_aesni = orig_use_aesni;
|
xaes->tweak.use_aesni = orig_use_aesni;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -179,6 +179,7 @@ enum {
|
|||||||
AES_ENC_TYPE = WC_CIPHER_AES, /* cipher unique type */
|
AES_ENC_TYPE = WC_CIPHER_AES, /* cipher unique type */
|
||||||
AES_ENCRYPTION = 0,
|
AES_ENCRYPTION = 0,
|
||||||
AES_DECRYPTION = 1,
|
AES_DECRYPTION = 1,
|
||||||
|
AES_ENCRYPTION_AND_DECRYPTION = 2,
|
||||||
|
|
||||||
AES_BLOCK_SIZE = 16,
|
AES_BLOCK_SIZE = 16,
|
||||||
|
|
||||||
@ -398,7 +399,8 @@ struct Aes {
|
|||||||
|
|
||||||
#ifdef WOLFSSL_AES_XTS
|
#ifdef WOLFSSL_AES_XTS
|
||||||
typedef struct XtsAes {
|
typedef struct XtsAes {
|
||||||
Aes aes;
|
Aes aes_encrypt;
|
||||||
|
Aes aes_decrypt;
|
||||||
Aes tweak;
|
Aes tweak;
|
||||||
} XtsAes;
|
} XtsAes;
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user