diff --git a/configure.ac b/configure.ac index ee2ebb9fc..192e6f241 100644 --- a/configure.ac +++ b/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" diff --git a/doc/dox_comments/header_files/aes.h b/doc/dox_comments/header_files/aes.h index 3a9b974f9..bbdee91e5 100644 --- a/doc/dox_comments/header_files/aes.h +++ b/doc/dox_comments/header_files/aes.h @@ -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); + + + diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 3836ca265..997490c13 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -76,9 +76,9 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits #include #endif -#ifdef WOLFSSL_AES_SIV +#if defined(WOLFSSL_AES_SIV) || defined(WOLFSSL_AES_EAX) #include -#endif +#endif /* WOLFSSL_AES_SIV || WOLFSSL_AES_EAX */ #if defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_AES) #include @@ -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 */ diff --git a/wolfcrypt/src/error.c b/wolfcrypt/src/error.c index 46dd7f300..929e0bfd0 100644 --- a/wolfcrypt/src/error.c +++ b/wolfcrypt/src/error.c @@ -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"; diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 7e030fc20..eef240e8b 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -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 diff --git a/wolfssl/wolfcrypt/aes.h b/wolfssl/wolfcrypt/aes.h index e81ccf0c6..c5d5a696c 100644 --- a/wolfssl/wolfcrypt/aes.h +++ b/wolfssl/wolfcrypt/aes.h @@ -142,6 +142,7 @@ WOLFSSL_LOCAL void GHASH(Gcm* gcm, const byte* a, word32 aSz, const byte* c, #include #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 diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index 39d63eb35..f689a40bb 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -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 */ diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 738be974c..b90b4d4c9 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -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 */