Add support for AES EAX mode, as described in https://eprint.iacr.org/2003/069

This commit is contained in:
Brett Nicholas 2023-09-25 17:37:26 -06:00 committed by Brett
parent ecf666a121
commit fafb9e81c0
8 changed files with 1303 additions and 17 deletions

View File

@ -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"

View File

@ -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);

View File

@ -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 */

View File

@ -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";

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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 */