Add support for AES EAX mode, as described in https://eprint.iacr.org/2003/069
This commit is contained in:
parent
ecf666a121
commit
fafb9e81c0
21
configure.ac
21
configure.ac
@ -723,6 +723,7 @@ then
|
||||
test "$enable_aesgcm_stream" = "" && enable_aesgcm_stream=yes
|
||||
test "$enable_aesccm" = "" && enable_aesccm=yes
|
||||
test "$enable_aesctr" = "" && enable_aesctr=yes
|
||||
test "$enable_aeseax" = "" && enable_aeseax=yes
|
||||
test "$enable_aesofb" = "" && enable_aesofb=yes
|
||||
test "$enable_aescfb" = "" && enable_aescfb=yes
|
||||
test "$enable_aescbc_length_checks" = "" && enable_aescbc_length_checks=yes
|
||||
@ -909,6 +910,7 @@ then
|
||||
test "$enable_aesgcm_stream" = "" && enable_aesgcm_stream=yes
|
||||
test "$enable_aesccm" = "" && enable_aesccm=yes
|
||||
test "$enable_aesctr" = "" && enable_aesctr=yes
|
||||
test "$enable_aeseax" = "" && enable_aeseax=yes
|
||||
test "$enable_aesofb" = "" && enable_aesofb=yes
|
||||
test "$enable_aescfb" = "" && enable_aescfb=yes
|
||||
test "$enable_aescbc_length_checks" = "" && enable_aescbc_length_checks=yes
|
||||
@ -2330,6 +2332,18 @@ then
|
||||
AM_CCASFLAGS="$AM_CCASFLAGS -DHAVE_AESCCM"
|
||||
fi
|
||||
|
||||
# AES-EAX
|
||||
AC_ARG_ENABLE([aeseax],
|
||||
[AS_HELP_STRING([--enable-aeseax],[Enable wolfSSL AES-EAX support (default: disabled)])],
|
||||
[ ENABLED_AESEAX=$enableval ],
|
||||
[ ENABLED_AESEAX=no ]
|
||||
)
|
||||
|
||||
if test "$ENABLED_AESEAX" = "yes"
|
||||
then
|
||||
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_EAX"
|
||||
fi
|
||||
|
||||
# AES-SIV (RFC 5297)
|
||||
AC_ARG_ENABLE([aessiv],
|
||||
[AS_HELP_STRING([--enable-aessiv],[Enable AES-SIV (RFC 5297) (default: disabled)])],
|
||||
@ -2342,13 +2356,13 @@ then
|
||||
ENABLED_AESSIV=yes
|
||||
fi
|
||||
|
||||
# AES-CTRf
|
||||
# AES-CTR
|
||||
AC_ARG_ENABLE([aesctr],
|
||||
[AS_HELP_STRING([--enable-aesctr],[Enable wolfSSL AES-CTR support (default: disabled)])],
|
||||
[ ENABLED_AESCTR=$enableval ],
|
||||
[ ENABLED_AESCTR=no ]
|
||||
)
|
||||
if test "$ENABLED_OPENVPN" = "yes" || test "$ENABLED_LIBSSH2" = "yes" || test "$ENABLED_AESSIV" = "yes" || test "$ENABLED_WOLFENGINE" = "yes"
|
||||
if test "$ENABLED_OPENVPN" = "yes" || test "$ENABLED_LIBSSH2" = "yes" || test "$ENABLED_AESSIV" = "yes" || test "$ENABLED_WOLFENGINE" = "yes" || test "$ENABLED_AESEAX" = "yes"
|
||||
then
|
||||
ENABLED_AESCTR=yes
|
||||
fi
|
||||
@ -4646,7 +4660,7 @@ AC_ARG_ENABLE([cmac],
|
||||
[ ENABLED_CMAC=no ]
|
||||
)
|
||||
|
||||
if test "$ENABLED_WPAS" != "no" || test "$ENABLED_NTP" = "yes" || test "$ENABLED_AESSIV" = "yes" || test "$ENABLED_WOLFENGINE" = "yes"
|
||||
if test "$ENABLED_WPAS" != "no" || test "$ENABLED_NTP" = "yes" || test "$ENABLED_AESSIV" = "yes" || test "$ENABLED_WOLFENGINE" = "yes" || test "$ENABLED_AESEAX" = "yes"
|
||||
then
|
||||
ENABLED_CMAC=yes
|
||||
fi
|
||||
@ -9366,6 +9380,7 @@ echo " * AES-CTR: $ENABLED_AESCTR"
|
||||
echo " * AES-CFB: $ENABLED_AESCFB"
|
||||
echo " * AES-OFB: $ENABLED_AESOFB"
|
||||
echo " * AES-SIV: $ENABLED_AESSIV"
|
||||
echo " * AES-EAX: $ENABLED_AESEAX"
|
||||
echo " * ARIA: $ENABLED_ARIA"
|
||||
echo " * DES3: $ENABLED_DES3"
|
||||
echo " * Camellia: $ENABLED_CAMELLIA"
|
||||
|
@ -1035,7 +1035,7 @@ int wc_AesSivEncrypt(const byte* key, word32 keySz, const byte* assoc,
|
||||
\return BAD_FUNC_ARG If key, SIV, or output buffer are NULL. Also returned
|
||||
if the key size isn't 32, 48, or 64 bytes.
|
||||
\return AES_SIV_AUTH_E If the SIV derived by S2V doesn't match the input
|
||||
SIV (see RFC 5297 2.7).
|
||||
SIV (see RFC 5297 2.7).
|
||||
\return Other Other negative error values returned if AES or CMAC operations
|
||||
fail.
|
||||
|
||||
@ -1072,3 +1072,553 @@ int wc_AesSivEncrypt(const byte* key, word32 keySz, const byte* assoc,
|
||||
int wc_AesSivDecrypt(const byte* key, word32 keySz, const byte* assoc,
|
||||
word32 assocSz, const byte* nonce, word32 nonceSz,
|
||||
const byte* in, word32 inSz, byte* siv, byte* out);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
\ingroup AES
|
||||
|
||||
\brief This function performs AES EAX encryption and authentication as
|
||||
described in "EAX: A Conventional Authenticated-Encryption Mode"
|
||||
(https://eprint.iacr.org/2003/069). It is a "one-shot" API that performs
|
||||
all encryption and authentication operations in one function call.
|
||||
|
||||
\return 0 on successful encryption.
|
||||
\return BAD_FUNC_ARG if input or output buffers are NULL. Also returned
|
||||
if the key size isn't a valid AES key size (16, 24, or 32 bytes)
|
||||
\return other negative error values returned if AES or CMAC operations
|
||||
fail.
|
||||
|
||||
\param key buffer containing the key to use
|
||||
\param keySz length of the key buffer in bytes
|
||||
\param[out] out buffer to hold the ciphertext. Should be the same length as
|
||||
the plaintext buffer
|
||||
\param in plaintext buffer to encrypt
|
||||
\param inSz length of plaintext buffer
|
||||
\param nonce the cryptographic nonce to use for EAX operations
|
||||
\param nonceSz length of nonce buffer in bytes
|
||||
\param[out] authTag pointer to the buffer in which to store the
|
||||
authentication tag
|
||||
\param authTagSz length of the desired authentication tag
|
||||
\param authIn pointer to the buffer containing input data to authenticate
|
||||
\param authInSz length of the input authentication data
|
||||
|
||||
_Example_
|
||||
\code
|
||||
byte key[] = { some 32, 48, or 64 byte key };
|
||||
byte nonce[] = {0x04, 0x5, 0x6};
|
||||
byte plainText[] = {0xDE, 0xAD, 0xBE, 0xEF};
|
||||
byte authIn[] = {0x01, 0x2, 0x3};
|
||||
|
||||
byte cipherText[sizeof(plainText)]; // output ciphertext
|
||||
byte authTag[length, up to AES_BLOCK_SIZE]; // output authTag
|
||||
|
||||
if (wc_AesEaxEncrypt(key, sizeof(key),
|
||||
cipherText, plainText, sizeof(plainText),
|
||||
nonce, sizeof(nonce),
|
||||
authTag, sizeof(authTag),
|
||||
authIn, sizeof(authIn)) != 0) {
|
||||
// failed to encrypt
|
||||
}
|
||||
|
||||
\endcode
|
||||
|
||||
\sa wc_AesEaxDecryptAuth
|
||||
|
||||
*/
|
||||
WOLFSSL_API int wc_AesEaxEncryptAuth(const byte* key, word32 keySz, byte* out,
|
||||
const byte* in, word32 inSz,
|
||||
const byte* nonce, word32 nonceSz,
|
||||
/* output computed auth tag */
|
||||
byte* authTag, word32 authTagSz,
|
||||
/* input data to authenticate */
|
||||
const byte* authIn, word32 authInSz);
|
||||
/*!
|
||||
\ingroup AES
|
||||
|
||||
\brief This function performs AES EAX decryption and authentication as
|
||||
described in "EAX: A Conventional Authenticated-Encryption Mode"
|
||||
(https://eprint.iacr.org/2003/069). It is a "one-shot" API that performs
|
||||
all decryption and authentication operations in one function call.
|
||||
|
||||
\return 0 on successful decryption
|
||||
\return BAD_FUNC_ARG if input or output buffers are NULL. Also returned
|
||||
if the key size isn't a valid AES key size (16, 24, or 32 bytes)
|
||||
\return AES_EAX_AUTH_E If the authentication tag does not match the
|
||||
supplied authentication code vector \c authTag
|
||||
\return other negative error values returned if AES or CMAC operations
|
||||
fail.
|
||||
|
||||
\param key byte buffer containing the key to use
|
||||
\param keySz length of the key buffer in bytes
|
||||
\param[out] out buffer to hold the plaintext. Should be the same length as
|
||||
the input ciphertext buffer
|
||||
\param in ciphertext buffer to decrypt
|
||||
\param inSz length of ciphertext buffer
|
||||
\param nonce the cryptographic nonce to use for EAX operations
|
||||
\param nonceSz length of nonce buffer in bytes
|
||||
\param authTag buffer that holds the authentication tag to check the
|
||||
authenticity of the data against
|
||||
\param authTagSz Length of the input authentication tag
|
||||
\param authIn pointer to the buffer containing input data to authenticate
|
||||
\param authInSz length of the input authentication data
|
||||
|
||||
_Example_
|
||||
\code
|
||||
byte key[] = { some 32, 48, or 64 byte key };
|
||||
byte nonce[] = {0x04, 0x5, 0x6};
|
||||
byte cipherText[] = {0xDE, 0xAD, 0xBE, 0xEF};
|
||||
byte authIn[] = {0x01, 0x2, 0x3};
|
||||
|
||||
byte plainText[sizeof(cipherText)]; // output plaintext
|
||||
byte authTag[length, up to AES_BLOCK_SIZE]; // output authTag
|
||||
|
||||
if (wc_AesEaxDecrypt(key, sizeof(key),
|
||||
cipherText, plainText, sizeof(plainText),
|
||||
nonce, sizeof(nonce),
|
||||
authTag, sizeof(authTag),
|
||||
authIn, sizeof(authIn)) != 0) {
|
||||
// failed to encrypt
|
||||
}
|
||||
|
||||
\endcode
|
||||
|
||||
\sa wc_AesEaxEncryptAuth
|
||||
|
||||
*/
|
||||
WOLFSSL_API int wc_AesEaxDecryptAuth(const byte* key, word32 keySz, byte* out,
|
||||
const byte* in, word32 inSz,
|
||||
const byte* nonce, word32 nonceSz,
|
||||
/* auth tag to verify against */
|
||||
const byte* authTag, word32 authTagSz,
|
||||
/* input data to authenticate */
|
||||
const byte* authIn, word32 authInSz);
|
||||
|
||||
/*!
|
||||
\ingroup AES
|
||||
\brief This function initializes an AesEax object for use in authenticated
|
||||
encryption or decryption. This function must be called on an AesEax
|
||||
object before using it with any of the AES EAX incremental API functions.
|
||||
It does not need to be called if using the one-shot EAX API functions.
|
||||
All AesEax instances initialized with this function need to be freed with
|
||||
a call to wc_AesEaxFree() when done using the instance.
|
||||
|
||||
\return 0 on success
|
||||
\return error code on failure
|
||||
|
||||
\param eax AES EAX structure holding the context of the AEAD operation
|
||||
\param key 16, 24, or 32 byte secret key for encryption and decryption
|
||||
\param keySz length of the supplied key in bytes
|
||||
\param nonce the cryptographic nonce to use for EAX operations
|
||||
\param nonceSz length of nonce buffer in bytes
|
||||
\param authIn (optional) input data to add to the authentication stream
|
||||
This argument should be NULL if not used
|
||||
\param authInSz size in bytes of the input authentication data
|
||||
|
||||
_Example_
|
||||
\code
|
||||
AesEax eax;
|
||||
key[] = { some 16, 24, or 32 byte length key };
|
||||
nonce[] = { some arbitrary length nonce };
|
||||
authIn[] = { some data to add to the authentication stream };
|
||||
plainText[] = {some plaintext data to encrypt};
|
||||
|
||||
cipherText[sizeof(plainText)]; // buffer to hold cipherText
|
||||
authTag[length, up to AES_BLOCK_SIZE]; // buffer to hold computed auth data
|
||||
|
||||
AesEax eax;
|
||||
|
||||
if ((ret = wc_AesEaxInit(eax,
|
||||
key, keySz,
|
||||
nonce, nonceSz,
|
||||
authIn, authInSz)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// if we wanted to add more auth data, we could provide it at this point,
|
||||
// otherwise we use NULL for the authIn parameter, with authIn size of 0
|
||||
if ((ret = wc_AesEaxEncryptUpdate(eax,
|
||||
cipherText, plainText, sizeof(plainText),
|
||||
NULL, 0)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((ret = wc_AesEaxEncryptFinal(eax, authTag, sizeof(authTag))) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
wc_AesEaxFree(eax);
|
||||
\endcode
|
||||
|
||||
\sa wc_AesEaxEncryptUpdate
|
||||
\sa wc_AesEaxDecryptUpdate
|
||||
\sa wc_AesEaxAuthDataUpdate
|
||||
\sa wc_AesEaxEncryptFinal
|
||||
\sa wc_AesEaxDecryptFinal
|
||||
\sa wc_AesEaxFree
|
||||
|
||||
*/
|
||||
WOLFSSL_API int wc_AesEaxInit(AesEax* eax,
|
||||
const byte* key, word32 keySz,
|
||||
const byte* nonce, word32 nonceSz,
|
||||
const byte* authIn, word32 authInSz);
|
||||
|
||||
/*!
|
||||
\ingroup AES
|
||||
\brief This function uses AES EAX to encrypt input data, and optionally, add
|
||||
more input data to the authentication stream. \c eax must have been
|
||||
previously initialized with a call to \ref wc_AesEaxInit.
|
||||
|
||||
\return 0 on success
|
||||
\return error code on failure
|
||||
|
||||
\param eax AES EAX structure holding the context of the AEAD operation
|
||||
\param[out] out output buffer holding the ciphertext
|
||||
\param in input buffer holding the plaintext to encrypt
|
||||
\param inSz size in bytes of the input data buffer
|
||||
\param authIn (optional) input data to add to the authentication stream
|
||||
This argument should be NULL if not used
|
||||
\param authInSz size in bytes of the input authentication data
|
||||
|
||||
_Example_
|
||||
\code
|
||||
AesEax eax;
|
||||
key[] = { some 16, 24, or 32 byte length key };
|
||||
nonce[] = { some arbitrary length nonce };
|
||||
authIn[] = { some data to add to the authentication stream };
|
||||
plainText[] = {some plaintext data to encrypt};
|
||||
|
||||
cipherText[sizeof(plainText)]; // buffer to hold cipherText
|
||||
authTag[length, up to AES_BLOCK_SIZE]; // buffer to hold computed auth data
|
||||
|
||||
AesEax eax;
|
||||
|
||||
if ((ret = wc_AesEaxInit(eax,
|
||||
key, keySz,
|
||||
nonce, nonceSz,
|
||||
authIn, authInSz)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// if we wanted to add more auth data, we could provide it at this point,
|
||||
// otherwise we use NULL for the authIn parameter, with authInSz of 0
|
||||
if ((ret = wc_AesEaxEncryptUpdate(eax,
|
||||
cipherText, plainText, sizeof(plainText),
|
||||
NULL, 0)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((ret = wc_AesEaxEncryptFinal(eax, authTag, sizeof(authTag))) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
wc_AesEaxFree(eax);
|
||||
\endcode
|
||||
|
||||
\sa wc_AesEaxInit
|
||||
\sa wc_AesEaxDecryptUpdate
|
||||
\sa wc_AesEaxAuthDataUpdate
|
||||
\sa wc_AesEaxEncryptFinal
|
||||
\sa wc_AesEaxDecryptFinal
|
||||
\sa wc_AesEaxFree
|
||||
|
||||
*/
|
||||
WOLFSSL_API int wc_AesEaxEncryptUpdate(AesEax* eax, byte* out,
|
||||
const byte* in, word32 inSz,
|
||||
const byte* authIn, word32 authInSz);
|
||||
|
||||
/*!
|
||||
\ingroup AES
|
||||
\brief This function uses AES EAX to decrypt input data, and optionally, add
|
||||
more input data to the authentication stream. \c eax must have been
|
||||
previously initialized with a call to \ref wc_AesEaxInit.
|
||||
|
||||
\return 0 on success
|
||||
\return error code on failure
|
||||
|
||||
\param eax AES EAX structure holding the context of the AEAD operation
|
||||
\param[out] out output buffer holding the decrypted plaintext
|
||||
\param in input buffer holding the ciphertext
|
||||
\param inSz size in bytes of the input data buffer
|
||||
\param authIn (optional) input data to add to the authentication stream
|
||||
This argument should be NULL if not used
|
||||
\param authInSz size in bytes of the input authentication data
|
||||
|
||||
|
||||
_Example_
|
||||
\code
|
||||
AesEax eax;
|
||||
key[] = { some 16, 24, or 32 byte length key };
|
||||
nonce[] = { some arbitrary length nonce };
|
||||
authIn[] = { some data to add to the authentication stream };
|
||||
cipherText[] = {some encrypted data};
|
||||
|
||||
plainText[sizeof(cipherText)]; // buffer to hold decrypted data
|
||||
// auth tag is generated elsewhere by the encrypt AEAD operation
|
||||
authTag[length, up to AES_BLOCK_SIZE] = { the auth tag };
|
||||
|
||||
AesEax eax;
|
||||
|
||||
if ((ret = wc_AesEaxInit(eax,
|
||||
key, keySz,
|
||||
nonce, nonceSz,
|
||||
authIn, authInSz)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// if we wanted to add more auth data, we could provide it at this point,
|
||||
// otherwise we use NULL for the authIn parameter, with authInSz of 0
|
||||
if ((ret = wc_AesEaxDecryptUpdate(eax,
|
||||
plainText, cipherText, sizeof(cipherText),
|
||||
NULL, 0)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((ret = wc_AesEaxDecryptFinal(eax, authTag, sizeof(authTag))) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
wc_AesEaxFree(eax);
|
||||
\endcode
|
||||
|
||||
\sa wc_AesEaxInit
|
||||
\sa wc_AesEaxEncryptUpdate
|
||||
\sa wc_AesEaxAuthDataUpdate
|
||||
\sa wc_AesEaxEncryptFinal
|
||||
\sa wc_AesEaxDecryptFinal
|
||||
\sa wc_AesEaxFree
|
||||
|
||||
*/
|
||||
WOLFSSL_API int wc_AesEaxDecryptUpdate(AesEax* eax, byte* out,
|
||||
const byte* in, word32 inSz,
|
||||
const byte* authIn, word32 authInSz);
|
||||
/*!
|
||||
\ingroup AES
|
||||
\brief This function adds input data to the authentication stream.
|
||||
\c eax must have been previously initialized with a call to
|
||||
\ref wc_AesEaxInit.
|
||||
|
||||
\return 0 on success
|
||||
\return error code on failure
|
||||
|
||||
\param eax AES EAX structure holding the context of the AEAD operation
|
||||
\param authIn input data to add to the authentication stream
|
||||
\param authInSz size in bytes of the input authentication data
|
||||
|
||||
_Example_
|
||||
\code
|
||||
AesEax eax;
|
||||
key[] = { some 16, 24, or 32 byte length key };
|
||||
nonce[] = { some arbitrary length nonce };
|
||||
authIn[] = { some data to add to the authentication stream };
|
||||
cipherText[] = {some encrypted data};
|
||||
|
||||
plainText[sizeof(cipherText)]; // buffer to hold decrypted data
|
||||
// auth tag is generated elsewhere by the encrypt AEAD operation
|
||||
authTag[length, up to AES_BLOCK_SIZE] = { the auth tag };
|
||||
|
||||
AesEax eax;
|
||||
|
||||
// No auth data to add here
|
||||
if ((ret = wc_AesEaxInit(eax,
|
||||
key, keySz,
|
||||
nonce, nonceSz,
|
||||
NULL, 0)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// No auth data to add here, added later with wc_AesEaxAuthDataUpdate
|
||||
if ((ret = wc_AesEaxDecryptUpdate(eax,
|
||||
plainText, cipherText, sizeof(cipherText),
|
||||
NULL, 0)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((ret = wc_AesEaxAuthDataUpdate(eax, authIn, sizeof(authIn))) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((ret = wc_AesEaxDecryptFinal(eax, authTag, sizeof(authTag))) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
wc_AesEaxFree(eax);
|
||||
\endcode
|
||||
|
||||
\sa wc_AesEaxInit
|
||||
\sa wc_AesEaxEncryptUpdate
|
||||
\sa wc_AesEaxDecryptUpdate
|
||||
\sa wc_AesEaxEncryptFinal
|
||||
\sa wc_AesEaxDecryptFinal
|
||||
\sa wc_AesEaxFree
|
||||
|
||||
*/
|
||||
WOLFSSL_API int wc_AesEaxAuthDataUpdate(AesEax* eax,
|
||||
const byte* authIn, word32 authInSz);
|
||||
|
||||
/*!
|
||||
\ingroup AES
|
||||
\brief This function finalizes the encrypt AEAD operation, producing an auth
|
||||
tag over the current authentication stream. \c eax must have been previously
|
||||
initialized with a call to \ref wc_AesEaxInit. When done using the \c AesEax
|
||||
context structure, make sure to free it using \ref wc_AesEaxFree.
|
||||
|
||||
\return 0 on success
|
||||
\return error code on failure
|
||||
|
||||
\param eax AES EAX structure holding the context of the AEAD operation
|
||||
\param authTag[out] buffer that will hold the computed auth tag
|
||||
\param authTagSz size in bytes of \c authTag
|
||||
|
||||
_Example_
|
||||
\code
|
||||
AesEax eax;
|
||||
key[] = { some 16, 24, or 32 byte length key };
|
||||
nonce[] = { some arbitrary length nonce };
|
||||
authIn[] = { some data to add to the authentication stream };
|
||||
plainText[] = {some plaintext data to encrypt};
|
||||
|
||||
cipherText[sizeof(plainText)]; // buffer to hold cipherText
|
||||
authTag[length, up to AES_BLOCK_SIZE]; // buffer to hold computed auth data
|
||||
|
||||
AesEax eax;
|
||||
|
||||
if ((ret = wc_AesEaxInit(eax,
|
||||
key, keySz,
|
||||
nonce, nonceSz,
|
||||
authIn, authInSz)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// if we wanted to add more auth data, we could provide it at this point,
|
||||
// otherwise we use NULL for the authIn parameter, with authInSz of 0
|
||||
if ((ret = wc_AesEaxEncryptUpdate(eax,
|
||||
cipherText, plainText, sizeof(plainText),
|
||||
NULL, 0)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((ret = wc_AesEaxEncryptFinal(eax, authTag, sizeof(authTag))) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
wc_AesEaxFree(eax);
|
||||
\endcode
|
||||
|
||||
\sa wc_AesEaxInit
|
||||
\sa wc_AesEaxEncryptUpdate
|
||||
\sa wc_AesEaxDecryptUpdate
|
||||
\sa wc_AesEaxAuthDataUpdate
|
||||
\sa wc_AesEaxDecryptFinal
|
||||
\sa wc_AesEaxFree
|
||||
|
||||
*/
|
||||
WOLFSSL_API int wc_AesEaxEncryptFinal(AesEax* eax,
|
||||
byte* authTag, word32 authTagSz);
|
||||
|
||||
/*!
|
||||
\ingroup AES
|
||||
\brief This function finalizes the decrypt AEAD operation, finalizing the
|
||||
auth tag computation and checking it for validity against the user supplied
|
||||
tag. \c eax must have been previously initialized with a call to
|
||||
\ref wc_AesEaxInit. When done using the \c AesEax context structure, make
|
||||
sure to free it using \ref wc_AesEaxFree.
|
||||
|
||||
\return 0 if data is authenticated succesfully
|
||||
\return AES_EAX_AUTH_E if the authentication tag does not match the
|
||||
supplied authentication code vector \c authIn
|
||||
\return other error code on failure
|
||||
|
||||
\param eax AES EAX structure holding the context of the AEAD operation
|
||||
\param authIn input auth tag to check computed auth tag against
|
||||
\param authInSz size in bytes of \c authIn
|
||||
|
||||
_Example_
|
||||
\code
|
||||
AesEax eax;
|
||||
key[] = { some 16, 24, or 32 byte length key };
|
||||
nonce[] = { some arbitrary length nonce };
|
||||
authIn[] = { some data to add to the authentication stream };
|
||||
cipherText[] = {some encrypted data};
|
||||
|
||||
plainText[sizeof(cipherText)]; // buffer to hold decrypted data
|
||||
// auth tag is generated elsewhere by the encrypt AEAD operation
|
||||
authTag[length, up to AES_BLOCK_SIZE] = { the auth tag };
|
||||
|
||||
AesEax eax;
|
||||
|
||||
if ((ret = wc_AesEaxInit(eax,
|
||||
key, keySz,
|
||||
nonce, nonceSz,
|
||||
authIn, authInSz)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// if we wanted to add more auth data, we could provide it at this point,
|
||||
// otherwise we use NULL for the authIn parameter, with authInSz of 0
|
||||
if ((ret = wc_AesEaxDecryptUpdate(eax,
|
||||
plainText, cipherText, sizeof(cipherText),
|
||||
NULL, 0)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((ret = wc_AesEaxDecryptFinal(eax, authTag, sizeof(authTag))) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
wc_AesEaxFree(eax);
|
||||
\endcode
|
||||
|
||||
\sa wc_AesEaxInit
|
||||
\sa wc_AesEaxEncryptUpdate
|
||||
\sa wc_AesEaxDecryptUpdate
|
||||
\sa wc_AesEaxAuthDataUpdate
|
||||
\sa wc_AesEaxEncryptFinal
|
||||
\sa wc_AesEaxFree
|
||||
|
||||
*/
|
||||
WOLFSSL_API int wc_AesEaxDecryptFinal(AesEax* eax,
|
||||
const byte* authIn, word32 authInSz);
|
||||
/*!
|
||||
\ingroup AES
|
||||
|
||||
\brief This frees up any resources, specifically keys, used by the Aes
|
||||
instance inside the AesEax wrapper struct. It should be called on the
|
||||
AesEax struct after it has been initialized with wc_AesEaxInit, and all
|
||||
desired EAX operations are complete.
|
||||
|
||||
\return 0 Success
|
||||
|
||||
\param eaxAES EAX instance to free
|
||||
|
||||
_Example_
|
||||
\code
|
||||
AesEax eax;
|
||||
|
||||
if(wc_AesEaxInit(eax, key, keySz, nonce, nonceSz, authIn, authInSz) != 0) {
|
||||
// handle errors, then free
|
||||
wc_AesEaxFree(&eax);
|
||||
}
|
||||
\endcode
|
||||
|
||||
\sa wc_AesEaxInit
|
||||
\sa wc_AesEaxEncryptUpdate
|
||||
\sa wc_AesEaxDecryptUpdate
|
||||
\sa wc_AesEaxAuthDataUpdate
|
||||
\sa wc_AesEaxEncryptFinal
|
||||
\sa wc_AesEaxDecryptFinal
|
||||
*/
|
||||
WOLFSSL_API int wc_AesEaxFree(AesEax* eax);
|
||||
|
||||
|
||||
|
||||
|
@ -76,9 +76,9 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits
|
||||
#include <wolfssl/wolfcrypt/port/nxp/se050_port.h>
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_AES_SIV
|
||||
#if defined(WOLFSSL_AES_SIV) || defined(WOLFSSL_AES_EAX)
|
||||
#include <wolfssl/wolfcrypt/cmac.h>
|
||||
#endif
|
||||
#endif /* WOLFSSL_AES_SIV || WOLFSSL_AES_EAX */
|
||||
|
||||
#if defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_AES)
|
||||
#include <wolfssl/wolfcrypt/port/psa/psa.h>
|
||||
@ -11682,4 +11682,503 @@ int wc_AesSivDecrypt(const byte* key, word32 keySz, const byte* assoc,
|
||||
|
||||
#endif /* WOLFSSL_AES_SIV */
|
||||
|
||||
#if defined(WOLFSSL_AES_EAX)
|
||||
|
||||
struct AesEax {
|
||||
Aes aes;
|
||||
Cmac nonceCmac;
|
||||
Cmac aadCmac;
|
||||
Cmac ciphertextCmac;
|
||||
byte nonceCmacFinal[AES_BLOCK_SIZE];
|
||||
byte aadCmacFinal[AES_BLOCK_SIZE];
|
||||
byte ciphertextCmacFinal[AES_BLOCK_SIZE];
|
||||
byte prefixBuf[AES_BLOCK_SIZE];
|
||||
};
|
||||
|
||||
/*
|
||||
* AES EAX one-shot API
|
||||
* Encrypts input data and computes an auth tag over the input
|
||||
* auth data and ciphertext
|
||||
*
|
||||
* Returns 0 on success
|
||||
* Returns error code on failure
|
||||
*/
|
||||
int wc_AesEaxEncryptAuth(const byte* key, word32 keySz, byte* out,
|
||||
const byte* in, word32 inSz,
|
||||
const byte* nonce, word32 nonceSz,
|
||||
/* output computed auth tag */
|
||||
byte* authTag, word32 authTagSz,
|
||||
/* input data to authenticate */
|
||||
const byte* authIn, word32 authInSz)
|
||||
{
|
||||
#if defined(WOLFSSL_SMALL_STACK)
|
||||
AesEax *eax;
|
||||
#else
|
||||
AesEax eax_mem;
|
||||
AesEax *eax = &eax_mem;
|
||||
#endif
|
||||
int ret;
|
||||
|
||||
if (key == NULL || out == NULL || in == NULL || nonce == NULL
|
||||
|| authTag == NULL || authIn == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
#if defined(WOLFSSL_SMALL_STACK)
|
||||
if ((eax = (AesEax *)XMALLOC(sizeof(AesEax),
|
||||
NULL,
|
||||
DYNAMIC_TYPE_AES_EAX)) == NULL) {
|
||||
return MEMORY_E;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((ret = wc_AesEaxInit(eax,
|
||||
key, keySz,
|
||||
nonce, nonceSz,
|
||||
authIn, authInSz)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((ret = wc_AesEaxEncryptUpdate(eax, out, in, inSz, NULL, 0)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((ret = wc_AesEaxEncryptFinal(eax, authTag, authTagSz)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
wc_AesEaxFree(eax);
|
||||
#if defined(WOLFSSL_SMALL_STACK)
|
||||
XFREE(eax, NULL, DYNAMIC_TYPE_AES_EAX);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* AES EAX one-shot API
|
||||
* Decrypts and authenticates data against a supplied auth tag
|
||||
*
|
||||
* Returns 0 on success
|
||||
* Returns error code on failure
|
||||
*/
|
||||
int wc_AesEaxDecryptAuth(const byte* key, word32 keySz, byte* out,
|
||||
const byte* in, word32 inSz,
|
||||
const byte* nonce, word32 nonceSz,
|
||||
/* auth tag to verify against */
|
||||
const byte* authTag, word32 authTagSz,
|
||||
/* input data to authenticate */
|
||||
const byte* authIn, word32 authInSz)
|
||||
{
|
||||
#if defined(WOLFSSL_SMALL_STACK)
|
||||
AesEax *eax;
|
||||
#else
|
||||
AesEax eax_mem;
|
||||
AesEax *eax = &eax_mem;
|
||||
#endif
|
||||
int ret;
|
||||
|
||||
if (key == NULL || out == NULL || in == NULL || nonce == NULL
|
||||
|| authTag == NULL || authIn == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
#if defined(WOLFSSL_SMALL_STACK)
|
||||
if ((eax = (AesEax *)XMALLOC(sizeof(AesEax),
|
||||
NULL,
|
||||
DYNAMIC_TYPE_AES_EAX)) == NULL) {
|
||||
return MEMORY_E;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((ret = wc_AesEaxInit(eax,
|
||||
key, keySz,
|
||||
nonce, nonceSz,
|
||||
authIn, authInSz)) != 0) {
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((ret = wc_AesEaxDecryptUpdate(eax, out, in, inSz, NULL, 0)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((ret = wc_AesEaxDecryptFinal(eax, authTag, authTagSz)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
wc_AesEaxFree(eax);
|
||||
#if defined(WOLFSSL_SMALL_STACK)
|
||||
XFREE(eax, NULL, DYNAMIC_TYPE_AES_EAX);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* AES EAX Incremental API:
|
||||
* Initializes an AES EAX encryption or decryption operation. This must be
|
||||
* called before any other EAX APIs are used on the AesEax struct
|
||||
*
|
||||
* Returns 0 on success
|
||||
* Returns error code on failure
|
||||
*/
|
||||
int wc_AesEaxInit(AesEax* eax,
|
||||
const byte* key, word32 keySz,
|
||||
const byte* nonce, word32 nonceSz,
|
||||
const byte* authIn, word32 authInSz)
|
||||
{
|
||||
int ret = 0;
|
||||
word32 cmacSize;
|
||||
|
||||
if (eax == NULL || key == NULL || nonce == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
XMEMSET(eax->prefixBuf, 0, sizeof(eax->prefixBuf));
|
||||
|
||||
if ((ret = wc_AesInit(&eax->aes, NULL, INVALID_DEVID)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
if ((ret = wc_AesSetKey(&eax->aes,
|
||||
key,
|
||||
keySz,
|
||||
NULL,
|
||||
AES_ENCRYPTION)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* OMAC the nonce to use as the IV for CTR encryption and auth tag chunk
|
||||
* N' = OMAC^0_K(N)
|
||||
*/
|
||||
if ((ret = wc_InitCmac(&eax->nonceCmac,
|
||||
key,
|
||||
keySz,
|
||||
WC_CMAC_AES,
|
||||
NULL)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = wc_CmacUpdate(&eax->nonceCmac,
|
||||
eax->prefixBuf,
|
||||
sizeof(eax->prefixBuf))) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = wc_CmacUpdate(&eax->nonceCmac, nonce, nonceSz)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
cmacSize = AES_BLOCK_SIZE;
|
||||
if ((ret = wc_CmacFinal(&eax->nonceCmac,
|
||||
eax->nonceCmacFinal,
|
||||
&cmacSize)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = wc_AesSetIV(&eax->aes, eax->nonceCmacFinal)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* start the OMAC used to build the auth tag chunk for the AD .
|
||||
* This CMAC is continued in subsequent update calls when more auth data is
|
||||
* provided
|
||||
* H' = OMAC^1_K(H)
|
||||
*/
|
||||
eax->prefixBuf[AES_BLOCK_SIZE-1] = 1;
|
||||
if ((ret = wc_InitCmac(&eax->aadCmac,
|
||||
key,
|
||||
keySz,
|
||||
WC_CMAC_AES,
|
||||
NULL)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = wc_CmacUpdate(&eax->aadCmac,
|
||||
eax->prefixBuf,
|
||||
sizeof(eax->prefixBuf))) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (authIn != NULL) {
|
||||
if ((ret = wc_CmacUpdate(&eax->aadCmac, authIn, authInSz)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* start the OMAC to create auth tag chunk for ciphertext. This MAC will be
|
||||
* updated in subsequent calls to encrypt/decrypt
|
||||
* C' = OMAC^2_K(C)
|
||||
*/
|
||||
eax->prefixBuf[AES_BLOCK_SIZE-1] = 2;
|
||||
if ((ret = wc_InitCmac(&eax->ciphertextCmac,
|
||||
key,
|
||||
keySz,
|
||||
WC_CMAC_AES,
|
||||
NULL)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = wc_CmacUpdate(&eax->ciphertextCmac,
|
||||
eax->prefixBuf,
|
||||
sizeof(eax->prefixBuf))) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* AES EAX Incremental API:
|
||||
* Encrypts input plaintext using AES EAX mode, adding optional auth data to
|
||||
* the authentication stream
|
||||
*
|
||||
* Returns 0 on success
|
||||
* Returns error code on failure
|
||||
*/
|
||||
int wc_AesEaxEncryptUpdate(AesEax* eax, byte* out,
|
||||
const byte* in, word32 inSz,
|
||||
const byte* authIn, word32 authInSz)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (eax == NULL || out == NULL || in == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encrypt the plaintext using AES CTR
|
||||
* C = CTR(M)
|
||||
*/
|
||||
if ((ret = wc_AesCtrEncrypt(&eax->aes, out, in, inSz)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* update OMAC with new ciphertext
|
||||
* C' = OMAC^2_K(C)
|
||||
*/
|
||||
if ((ret = wc_CmacUpdate(&eax->ciphertextCmac, out, inSz)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* If there exists new auth data, update the OMAC for that as well */
|
||||
if (authIn != NULL) {
|
||||
if ((ret = wc_CmacUpdate(&eax->aadCmac, authIn, authInSz)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* AES EAX Incremental API:
|
||||
* Decrypts input ciphertext using AES EAX mode, adding optional auth data to
|
||||
* the authentication stream
|
||||
*
|
||||
* Returns 0 on sucess
|
||||
* Returns error code on failure
|
||||
*/
|
||||
int wc_AesEaxDecryptUpdate(AesEax* eax, byte* out,
|
||||
const byte* in, word32 inSz,
|
||||
const byte* authIn, word32 authInSz)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (eax == NULL || out == NULL || in == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decrypt the plaintext using AES CTR
|
||||
* C = CTR(M)
|
||||
*/
|
||||
if ((ret = wc_AesCtrEncrypt(&eax->aes, out, in, inSz)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* update OMAC with new ciphertext
|
||||
* C' = OMAC^2_K(C)
|
||||
*/
|
||||
if ((ret = wc_CmacUpdate(&eax->ciphertextCmac, in, inSz)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* If there exists new auth data, update the OMAC for that as well */
|
||||
if (authIn != NULL) {
|
||||
if ((ret = wc_CmacUpdate(&eax->aadCmac, authIn, authInSz)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* AES EAX Incremental API:
|
||||
* Provides additional auth data information to the authentication
|
||||
* stream for an authenticated encryption or decryption operation
|
||||
*
|
||||
* Returns 0 on success
|
||||
* Returns error code on failure
|
||||
*/
|
||||
int wc_AesEaxAuthDataUpdate(AesEax* eax, const byte* authIn, word32 authInSz)
|
||||
{
|
||||
return wc_CmacUpdate(&eax->aadCmac, authIn, authInSz);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* AES EAX Incremental API:
|
||||
* Finalizes the authenticated encryption operation, computing the auth tag
|
||||
* over previously supplied auth data and computed ciphertext
|
||||
*
|
||||
* Returns 0 on success
|
||||
* Returns error code on failure
|
||||
*/
|
||||
int wc_AesEaxEncryptFinal(AesEax* eax, byte* authTag, word32 authTagSz)
|
||||
{
|
||||
word32 cmacSize;
|
||||
int ret;
|
||||
word32 i;
|
||||
|
||||
if (eax == NULL || authTag == NULL || authTagSz > AES_BLOCK_SIZE) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/* Complete the OMAC for the ciphertext */
|
||||
cmacSize = AES_BLOCK_SIZE;
|
||||
if ((ret = wc_CmacFinal(&eax->ciphertextCmac,
|
||||
eax->ciphertextCmacFinal,
|
||||
&cmacSize)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Complete the OMAC for auth data */
|
||||
cmacSize = AES_BLOCK_SIZE;
|
||||
if ((ret = wc_CmacFinal(&eax->aadCmac,
|
||||
eax->aadCmacFinal,
|
||||
&cmacSize)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Concatenate all three auth tag chunks into the final tag, truncating
|
||||
* at the specified tag length
|
||||
* T = Tag [first authTagSz bytes]
|
||||
*/
|
||||
for (i = 0; i < authTagSz; i++) {
|
||||
authTag[i] = eax->nonceCmacFinal[i]
|
||||
^ eax->aadCmacFinal[i]
|
||||
^ eax->ciphertextCmacFinal[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* AES EAX Incremental API:
|
||||
* Finalizes the authenticated decryption operation, computing the auth tag
|
||||
* for the previously supplied auth data and cipher text and validating it
|
||||
* against a provided auth tag
|
||||
*
|
||||
* Returns 0 on success
|
||||
* Return error code for failure
|
||||
*/
|
||||
int wc_AesEaxDecryptFinal(AesEax* eax,
|
||||
const byte* authIn, word32 authInSz)
|
||||
{
|
||||
int ret;
|
||||
word32 i;
|
||||
word32 cmacSize;
|
||||
|
||||
#if defined(WOLFSSL_SMALL_STACK)
|
||||
byte *authTag;
|
||||
#else
|
||||
byte authTag[AES_BLOCK_SIZE];
|
||||
#endif
|
||||
|
||||
if (eax == NULL || authIn == NULL || authInSz > AES_BLOCK_SIZE) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/* Complete the OMAC for the ciphertext */
|
||||
cmacSize = AES_BLOCK_SIZE;
|
||||
if ((ret = wc_CmacFinal(&eax->ciphertextCmac,
|
||||
eax->ciphertextCmacFinal,
|
||||
&cmacSize)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Complete the OMAC for auth data */
|
||||
cmacSize = AES_BLOCK_SIZE;
|
||||
if ((ret = wc_CmacFinal(&eax->aadCmac,
|
||||
eax->aadCmacFinal,
|
||||
&cmacSize)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(WOLFSSL_SMALL_STACK)
|
||||
authTag = (byte*)XMALLOC(AES_BLOCK_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (authTag == NULL) {
|
||||
return MEMORY_E;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Concatenate all three auth tag chunks into the final tag, truncating
|
||||
* at the specified tag length
|
||||
* T = Tag [first authInSz bytes]
|
||||
*/
|
||||
for (i = 0; i < authInSz; i++) {
|
||||
authTag[i] = eax->nonceCmacFinal[i]
|
||||
^ eax->aadCmacFinal[i]
|
||||
^ eax->ciphertextCmacFinal[i];
|
||||
}
|
||||
|
||||
if (ConstantCompare((const byte*)authTag, authIn, authInSz) != 0) {
|
||||
ret = AES_EAX_AUTH_E;
|
||||
}
|
||||
else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
#if defined(WOLFSSL_SMALL_STACK)
|
||||
XFREE(authTag, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Frees the underlying AES context. Must be called when done using the AES EAX
|
||||
* context structure
|
||||
*
|
||||
* Returns 0 on success
|
||||
* Returns error code on failure
|
||||
*/
|
||||
int wc_AesEaxFree(AesEax* eax)
|
||||
{
|
||||
if (eax == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
wc_AesFree(&eax->aes);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* WOLFSSL_AES_EAX */
|
||||
|
||||
#endif /* !NO_AES */
|
||||
|
@ -598,6 +598,9 @@ const char* wc_GetErrorString(int error)
|
||||
case FIPS_DEGRADED_E:
|
||||
return "FIPS module in DEGRADED mode";
|
||||
|
||||
case AES_EAX_AUTH_E:
|
||||
return "AES-EAX Authentication check fail";
|
||||
|
||||
default:
|
||||
return "unknown error number";
|
||||
|
||||
|
@ -674,6 +674,10 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t certpiv_test(void);
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aes_siv_test(void);
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSL_AES_EAX)
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aes_eax_test(void);
|
||||
#endif /* WOLFSSL_AES_EAX */
|
||||
|
||||
/* General big buffer size for many tests. */
|
||||
#define FOURK_BUF 4096
|
||||
|
||||
@ -1435,6 +1439,13 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSL_AES_EAX)
|
||||
if ( (ret = aes_eax_test()) != 0)
|
||||
TEST_FAIL("AES-EAX test failed!\n", ret);
|
||||
else
|
||||
TEST_PASS("AES-EAX test passed!\n");
|
||||
#endif /* WOLFSSL_AES_EAX */
|
||||
|
||||
#ifdef HAVE_ARIA
|
||||
if ( (ret = ariagcm_test(MC_ALGID_ARIA_128BITKEY)) != 0)
|
||||
TEST_FAIL("ARIA128 test failed!\n", ret);
|
||||
@ -2052,9 +2063,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t error_test(void)
|
||||
int i;
|
||||
int j = 0;
|
||||
/* Values that are not or no longer error codes. */
|
||||
int missing[] = { -122, -123, -124, -128, -129, -159,
|
||||
-163, -164, -165, -166, -167, -168, -169, -233,
|
||||
0 };
|
||||
int missing[] = { -123, -124, -128, -129, -159, -163, -164,
|
||||
-165, -166, -167, -168, -169, -233, 0 };
|
||||
|
||||
/* Check that all errors have a string and it's the same through the two
|
||||
* APIs. Check that the values that are not errors map to the unknown
|
||||
@ -12973,6 +12983,161 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aesccm_test(void)
|
||||
#endif /* HAVE_AESCCM */
|
||||
|
||||
|
||||
#if defined(WOLFSSL_AES_EAX)
|
||||
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aes_eax_test(void)
|
||||
{
|
||||
typedef struct {
|
||||
byte key[AES_256_KEY_SIZE];
|
||||
int key_length;
|
||||
byte iv[AES_BLOCK_SIZE];
|
||||
int iv_length;
|
||||
byte aad[AES_BLOCK_SIZE * 2];
|
||||
int aad_length;
|
||||
byte msg[AES_BLOCK_SIZE * 2];
|
||||
int msg_length;
|
||||
byte ct[AES_BLOCK_SIZE * 2];
|
||||
int ct_length;
|
||||
byte tag[AES_BLOCK_SIZE];
|
||||
int tag_length;
|
||||
int valid;
|
||||
} AadVector;
|
||||
|
||||
/* A small selection of Google wycheproof vectors that use vectors
|
||||
* from the original paper: eprint.iacr.org/2003/069
|
||||
* https://github.com/google/wycheproof/blob/master/testvectors/aes_eax_test.json
|
||||
*/
|
||||
WOLFSSL_SMALL_STACK_STATIC const AadVector vectors[] = {
|
||||
/* Vector from paper - empty message with auth data */
|
||||
{
|
||||
/* key, key length */
|
||||
{0x23, 0x39, 0x52, 0xde, 0xe4, 0xd5, 0xed, 0x5f,
|
||||
0x9b, 0x9c, 0x6d, 0x6f, 0xf8, 0x0f, 0xf4, 0x78}, 16,
|
||||
/* iv, iv length */
|
||||
{0x62, 0xec, 0x67, 0xf9, 0xc3, 0xa4, 0xa4, 0x07,
|
||||
0xfc, 0xb2, 0xa8, 0xc4, 0x90, 0x31, 0xa8, 0xb3}, 16,
|
||||
/* aad, aad length */
|
||||
{0x6b, 0xfb, 0x91, 0x4f, 0xd0, 0x7e, 0xae, 0x6b}, 8,
|
||||
/* msg, msg length */
|
||||
{0}, 0,
|
||||
/* ct, ct length */
|
||||
{0}, 0,
|
||||
/* tag, tag length */
|
||||
{0xe0, 0x37, 0x83, 0x0e, 0x83, 0x89, 0xf2,
|
||||
0x7b, 0x02, 0x5a, 0x2d, 0x65, 0x27, 0xe7, 0x9d, 0x01}, 16,
|
||||
/* valid */
|
||||
1,
|
||||
},
|
||||
/* Vector from paper - no auth data, valid auth tag */
|
||||
{
|
||||
/* key, key length */
|
||||
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}, 16,
|
||||
/* iv , iv length */
|
||||
{0x3c, 0x8c, 0xc2, 0x97, 0x0a, 0x00, 0x8f, 0x75,
|
||||
0xcc, 0x5b, 0xea, 0xe2, 0x84, 0x72, 0x58, 0xc2}, 16,
|
||||
/* aad, aad length */
|
||||
{0}, 0,
|
||||
/* msg, msg length */
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 32,
|
||||
/* ct, ct length */
|
||||
{0x3c, 0x44, 0x1f, 0x32, 0xce, 0x07, 0x82, 0x23,
|
||||
0x64, 0xd7, 0xa2, 0x99, 0x0e, 0x50, 0xbb, 0x13,
|
||||
0xd7, 0xb0, 0x2a, 0x26, 0x96, 0x9e, 0x4a, 0x93,
|
||||
0x7e, 0x5e, 0x90, 0x73, 0xb0, 0xd9, 0xc9, 0x68}, 32,
|
||||
/* tag, tag length */
|
||||
{0xdb, 0x90, 0xbd, 0xb3, 0xda, 0x3d, 0x00, 0xaf,
|
||||
0xd0, 0xfc, 0x6a, 0x83, 0x55, 0x1d, 0xa9, 0x5e}, 16,
|
||||
/* valid */
|
||||
1,
|
||||
},
|
||||
/* Vector from paper - no auth data with invalid auth tag */
|
||||
{
|
||||
/* key, key length */
|
||||
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}, 16,
|
||||
/* iv, iv length */
|
||||
{0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
|
||||
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f}, 16,
|
||||
/* aad, aad length */
|
||||
{0}, 0,
|
||||
/* msg, msg length */
|
||||
{0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
|
||||
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f}, 16,
|
||||
/* ct , ct length */
|
||||
{0x29, 0xa0, 0x91, 0x4f, 0xec, 0x4b, 0xef, 0x54,
|
||||
0xba, 0xbf, 0x66, 0x13, 0xa9, 0xf9, 0xcd, 0x70}, 16,
|
||||
/* tag, tag length */
|
||||
{0xe7, 0x0e, 0x7c, 0x50, 0x13, 0xa6, 0xdb, 0xf2,
|
||||
0x52, 0x98, 0xb1, 0x92, 0x9b, 0xc3, 0x56, 0xa7}, 16,
|
||||
/* valid */
|
||||
0,
|
||||
},
|
||||
};
|
||||
|
||||
WOLFSSL_SMALL_STACK_STATIC byte ciphertext[sizeof(vectors[0].ct)];
|
||||
WOLFSSL_SMALL_STACK_STATIC byte authtag[sizeof(vectors[0].tag)];
|
||||
wc_test_ret_t ret;
|
||||
int i;
|
||||
int len;
|
||||
|
||||
for (i = 0; i < (int)(sizeof(vectors)/sizeof(vectors[0])); i++) {
|
||||
|
||||
XMEMSET(ciphertext, 0, sizeof(ciphertext));
|
||||
|
||||
len = sizeof(authtag);
|
||||
ret = wc_AesEaxEncryptAuth(vectors[i].key, vectors[i].key_length,
|
||||
ciphertext,
|
||||
vectors[i].msg, vectors[i].msg_length,
|
||||
vectors[i].iv, vectors[i].iv_length,
|
||||
authtag, len,
|
||||
vectors[i].aad, vectors[i].aad_length);
|
||||
if (ret != 0) {
|
||||
return WC_TEST_RET_ENC_EC(ret);
|
||||
}
|
||||
|
||||
/* check ciphertext matches vector */
|
||||
if (XMEMCMP(ciphertext, vectors[i].ct, vectors[i].ct_length)) {
|
||||
return WC_TEST_RET_ENC_NC;
|
||||
}
|
||||
|
||||
/* check that tag matches vector only for vectors marked as valid */
|
||||
ret = XMEMCMP(authtag, vectors[i].tag, len);
|
||||
if (vectors[i].valid == 1 && ret != 0 ) {
|
||||
return WC_TEST_RET_ENC_NC;
|
||||
}
|
||||
else if (vectors[i].valid == 0 && ret == 0) {
|
||||
return WC_TEST_RET_ENC_NC;
|
||||
}
|
||||
|
||||
XMEMSET(ciphertext, 0, sizeof(ciphertext));
|
||||
|
||||
ret = wc_AesEaxDecryptAuth(vectors[i].key, vectors[i].key_length,
|
||||
ciphertext,
|
||||
vectors[i].ct, vectors[i].ct_length,
|
||||
vectors[i].iv, vectors[i].iv_length,
|
||||
authtag, len,
|
||||
vectors[i].aad, vectors[i].aad_length);
|
||||
if (ret != 0) {
|
||||
return WC_TEST_RET_ENC_EC(ret);
|
||||
}
|
||||
|
||||
/* check decrypted ciphertext matches vector plaintext */
|
||||
if (XMEMCMP(ciphertext, vectors[i].msg, vectors[i].msg_length)) {
|
||||
return WC_TEST_RET_ENC_NC;
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* WOLFSSL_AES_EAX */
|
||||
|
||||
|
||||
|
||||
#ifdef HAVE_AES_KEYWRAP
|
||||
|
||||
#define MAX_KEYWRAP_TEST_OUTLEN 40
|
||||
|
@ -142,6 +142,7 @@ WOLFSSL_LOCAL void GHASH(Gcm* gcm, const byte* a, word32 aSz, const byte* c,
|
||||
#include <wolfssl/wolfcrypt/port/maxim/maxq10xx.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -525,6 +526,7 @@ WOLFSSL_API int wc_AesGcmDecryptFinal(Aes* aes, const byte* authTag,
|
||||
byte* authTag, word32 authTagSz,
|
||||
const byte* authIn, word32 authInSz);
|
||||
#endif /* HAVE_AESCCM */
|
||||
|
||||
#ifdef HAVE_AES_KEYWRAP
|
||||
WOLFSSL_API int wc_AesKeyWrap(const byte* key, word32 keySz,
|
||||
const byte* in, word32 inSz,
|
||||
@ -586,6 +588,55 @@ int wc_AesSivDecrypt(const byte* key, word32 keySz, const byte* assoc,
|
||||
const byte* in, word32 inSz, byte* siv, byte* out);
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_AES_EAX
|
||||
|
||||
typedef struct AesEax AesEax;
|
||||
|
||||
/* One-shot API */
|
||||
WOLFSSL_API int wc_AesEaxEncryptAuth(const byte* key, word32 keySz, byte* out,
|
||||
const byte* in, word32 inSz,
|
||||
const byte* nonce, word32 nonceSz,
|
||||
/* output computed auth tag */
|
||||
byte* authTag, word32 authTagSz,
|
||||
/* input data to authenticate (header) */
|
||||
const byte* authIn, word32 authInSz);
|
||||
|
||||
WOLFSSL_API int wc_AesEaxDecryptAuth(const byte* key, word32 keySz, byte* out,
|
||||
const byte* in, word32 inSz,
|
||||
const byte* nonce, word32 nonceSz,
|
||||
/* auth tag to verify against */
|
||||
const byte* authTag, word32 authTagSz,
|
||||
/* input data to authenticate (header) */
|
||||
const byte* authIn, word32 authInSz);
|
||||
|
||||
/* Incremental API */
|
||||
WOLFSSL_API int wc_AesEaxInit(AesEax* eax,
|
||||
const byte* key, word32 keySz,
|
||||
const byte* nonce, word32 nonceSz,
|
||||
const byte* authIn, word32 authInSz);
|
||||
|
||||
WOLFSSL_API int wc_AesEaxEncryptUpdate(AesEax* eax, byte* out,
|
||||
const byte* in, word32 inSz,
|
||||
const byte* authIn, word32 authInSz);
|
||||
|
||||
WOLFSSL_API int wc_AesEaxDecryptUpdate(AesEax* eax, byte* out,
|
||||
const byte* in, word32 inSz,
|
||||
const byte* authIn, word32 authInSz);
|
||||
|
||||
WOLFSSL_API int wc_AesEaxAuthDataUpdate(AesEax* eax,
|
||||
const byte* authIn, word32 authInSz);
|
||||
|
||||
WOLFSSL_API int wc_AesEaxEncryptFinal(AesEax* eax,
|
||||
byte* authTag, word32 authTagSz);
|
||||
|
||||
WOLFSSL_API int wc_AesEaxDecryptFinal(AesEax* eax,
|
||||
const byte* authIn, word32 authInSz);
|
||||
|
||||
WOLFSSL_API int wc_AesEaxFree(AesEax* eax);
|
||||
|
||||
#endif /* WOLFSSL_AES_EAX */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
@ -64,6 +64,8 @@ enum {
|
||||
MP_CMP_E = -120, /* mp_cmp error state */
|
||||
MP_ZERO_E = -121, /* got a mp zero result, not expected */
|
||||
|
||||
AES_EAX_AUTH_E = -122, /* AES-EAX Authentication check failure */
|
||||
|
||||
MEMORY_E = -125, /* out of memory error */
|
||||
VAR_STATE_CHANGE_E = -126, /* var state modified by different thread */
|
||||
FIPS_DEGRADED_E = -127, /* FIPS Module in degraded mode */
|
||||
|
@ -1012,14 +1012,15 @@ typedef struct w64wrapper {
|
||||
DYNAMIC_TYPE_DILITHIUM = 97,
|
||||
DYNAMIC_TYPE_SPHINCS = 98,
|
||||
DYNAMIC_TYPE_SM4_BUFFER = 99,
|
||||
DYNAMIC_TYPE_SNIFFER_SERVER = 1000,
|
||||
DYNAMIC_TYPE_SNIFFER_SESSION = 1001,
|
||||
DYNAMIC_TYPE_SNIFFER_PB = 1002,
|
||||
DYNAMIC_TYPE_SNIFFER_PB_BUFFER = 1003,
|
||||
DYNAMIC_TYPE_SNIFFER_TICKET_ID = 1004,
|
||||
DYNAMIC_TYPE_SNIFFER_NAMED_KEY = 1005,
|
||||
DYNAMIC_TYPE_SNIFFER_KEY = 1006,
|
||||
DYNAMIC_TYPE_SNIFFER_KEYLOG_NODE = 1007
|
||||
DYNAMIC_TYPE_SNIFFER_SERVER = 1000,
|
||||
DYNAMIC_TYPE_SNIFFER_SESSION = 1001,
|
||||
DYNAMIC_TYPE_SNIFFER_PB = 1002,
|
||||
DYNAMIC_TYPE_SNIFFER_PB_BUFFER = 1003,
|
||||
DYNAMIC_TYPE_SNIFFER_TICKET_ID = 1004,
|
||||
DYNAMIC_TYPE_SNIFFER_NAMED_KEY = 1005,
|
||||
DYNAMIC_TYPE_SNIFFER_KEY = 1006,
|
||||
DYNAMIC_TYPE_SNIFFER_KEYLOG_NODE = 1007,
|
||||
DYNAMIC_TYPE_AES_EAX = 1008,
|
||||
};
|
||||
|
||||
/* max error buffer string size */
|
||||
|
Loading…
Reference in New Issue
Block a user