mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-07-30 02:37:28 +02:00
Merge pull request #8307 from julek-wolfssl/ascon
Initial ASCON hash256 and AEAD128 support based on NIST SP 800-232 ipd
This commit is contained in:
2
.github/workflows/os-check.yml
vendored
2
.github/workflows/os-check.yml
vendored
@ -40,6 +40,8 @@ jobs:
|
||||
--enable-dtls-mtu',
|
||||
'--enable-dtls --enable-dtlscid --enable-dtls13 --enable-secure-renegotiation
|
||||
--enable-psk --enable-aesccm --enable-nullcipher CPPFLAGS=-DWOLFSSL_STATIC_RSA',
|
||||
'--enable-ascon --enable-experimental',
|
||||
'--enable-ascon CPPFLAGS=-DWOLFSSL_ASCON_UNROLL --enable-experimental',
|
||||
]
|
||||
name: make check
|
||||
if: github.repository_owner == 'wolfssl'
|
||||
|
@ -564,6 +564,7 @@ WOLFSSL_ALLOW_TLS_SHA1
|
||||
WOLFSSL_ALTERNATIVE_DOWNGRADE
|
||||
WOLFSSL_ALT_NAMES_NO_REV
|
||||
WOLFSSL_ARM_ARCH_NEON_64BIT
|
||||
WOLFSSL_ASCON_UNROLL
|
||||
WOLFSSL_ASNC_CRYPT
|
||||
WOLFSSL_ASN_EXTRA
|
||||
WOLFSSL_ASN_INT_LEAD_0_ANY
|
||||
|
13
configure.ac
13
configure.ac
@ -6055,6 +6055,17 @@ then
|
||||
AM_CFLAGS="$AM_CFLAGS -DHAVE_XCHACHA"
|
||||
fi
|
||||
|
||||
# ASCON
|
||||
AC_ARG_ENABLE([ascon],
|
||||
[AS_HELP_STRING([--enable-ascon],[Enable ASCON (default: disabled).])],
|
||||
[ ENABLED_ASCON=$enableval ],
|
||||
[ ENABLED_ASCON=no]
|
||||
)
|
||||
|
||||
if test "$ENABLED_ASCON" = "yes"
|
||||
then
|
||||
AM_CFLAGS="$AM_CFLAGS -DHAVE_ASCON"
|
||||
fi
|
||||
|
||||
# Hash DRBG
|
||||
AC_ARG_ENABLE([hashdrbg],
|
||||
@ -10073,6 +10084,7 @@ AM_CONDITIONAL([BUILD_SHA3],[test "x$ENABLED_SHA3" != "xno" || test "x$ENABLED_U
|
||||
AM_CONDITIONAL([BUILD_POLY1305],[test "x$ENABLED_POLY1305" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"])
|
||||
AM_CONDITIONAL([BUILD_CHACHA],[test "x$ENABLED_CHACHA" = "xyes" || test "x$ENABLED_CHACHA" = "xnoasm" || test "x$ENABLED_USERSETTINGS" = "xyes"])
|
||||
AM_CONDITIONAL([BUILD_XCHACHA],[test "x$ENABLED_XCHACHA" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"])
|
||||
AM_CONDITIONAL([BUILD_ASCON],[test "x$ENABLED_ASCON" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"])
|
||||
AM_CONDITIONAL([BUILD_SM2],[test "x$ENABLED_SM2" != "xno" || test "x$ENABLED_USERSETTINGS" = "xyes"])
|
||||
AM_CONDITIONAL([BUILD_SM3],[test "x$ENABLED_SM3" != "xno" || test "x$ENABLED_USERSETTINGS" = "xyes"])
|
||||
AM_CONDITIONAL([BUILD_SM4],[test "x$ENABLED_SM4" != "xno" || test "x$ENABLED_USERSETTINGS" = "xyes"])
|
||||
@ -10473,6 +10485,7 @@ echo " * AES-EAX: $ENABLED_AESEAX"
|
||||
echo " * AES Bitspliced: $ENABLED_AESBS"
|
||||
echo " * AES Key Wrap: $ENABLED_AESKEYWRAP"
|
||||
echo " * ARIA: $ENABLED_ARIA"
|
||||
echo " * ASCON: $ENABLED_ASCON"
|
||||
echo " * DES3: $ENABLED_DES3"
|
||||
echo " * DES3 TLS Suites: $ENABLED_DES3_TLS_SUITES"
|
||||
echo " * Camellia: $ENABLED_CAMELLIA"
|
||||
|
469
doc/dox_comments/header_files/ascon.h
Normal file
469
doc/dox_comments/header_files/ascon.h
Normal file
@ -0,0 +1,469 @@
|
||||
/*!
|
||||
\ingroup ASCON
|
||||
\brief This function initializes the ASCON context for hashing.
|
||||
|
||||
\return 0 on success.
|
||||
\return BAD_FUNC_ARG if the context pointer is NULL.
|
||||
|
||||
\param a pointer to the ASCON context to initialize.
|
||||
|
||||
_Example_
|
||||
\code
|
||||
wc_AsconHash256 a;
|
||||
byte data[] = {0x01, 0x02, 0x03};
|
||||
byte hash[ASCON_HASH256_SZ];
|
||||
|
||||
if (wc_AsconHash256_Init(&a) != 0)
|
||||
// handle error
|
||||
if (wc_AsconHash256_Update(&ctx, data, sizeof(data)) != 0)
|
||||
// handle error
|
||||
if (wc_AsconHash256_Final(&ctx, hash, sizeof(hash)) != 0)
|
||||
// handle error
|
||||
// hash contains the final hash
|
||||
\endcode
|
||||
|
||||
\sa wc_AsconHash256_Update
|
||||
\sa wc_AsconHash256_Final
|
||||
*/
|
||||
int wc_AsconHash256_Init(wc_AsconHash256* a);
|
||||
|
||||
/*!
|
||||
\ingroup ASCON
|
||||
\brief This function updates the ASCON hash with the input data.
|
||||
|
||||
\return 0 on success.
|
||||
\return BAD_FUNC_ARG if the context or input pointer is NULL.
|
||||
|
||||
\param ctx pointer to the ASCON context.
|
||||
\param in pointer to the input data.
|
||||
\param inSz size of the input data.
|
||||
|
||||
_Example_
|
||||
\code
|
||||
wc_AsconHash256 a;
|
||||
byte data[] = {0x01, 0x02, 0x03};
|
||||
byte hash[ASCON_HASH256_SZ];
|
||||
|
||||
if (wc_AsconHash256_Init(&a) != 0)
|
||||
// handle error
|
||||
if (wc_AsconHash256_Update(&ctx, data, sizeof(data)) != 0)
|
||||
// handle error
|
||||
if (wc_AsconHash256_Final(&ctx, hash, sizeof(hash)) != 0)
|
||||
// handle error
|
||||
// hash contains the final hash
|
||||
\endcode
|
||||
|
||||
\sa wc_AsconHash256_Init
|
||||
\sa wc_AsconHash256_Final
|
||||
*/
|
||||
int wc_AsconHash256_Update(wc_AsconHash256* a, const byte* data, word32 dataSz);
|
||||
|
||||
/*!
|
||||
\ingroup ASCON
|
||||
\brief This function finalizes the ASCON hash and produces the output.
|
||||
|
||||
\return 0 on success.
|
||||
\return BAD_FUNC_ARG if the context or output pointer is NULL.
|
||||
|
||||
\param ctx pointer to the ASCON context.
|
||||
\param out pointer to the output buffer.
|
||||
\param outSz size of the output buffer, should be at least ASCON_HASH256_SZ.
|
||||
|
||||
_Example_
|
||||
\code
|
||||
wc_AsconHash256 a;
|
||||
byte data[] = {0x01, 0x02, 0x03};
|
||||
byte hash[ASCON_HASH256_SZ];
|
||||
|
||||
if (wc_AsconHash256_Init(&a) != 0)
|
||||
// handle error
|
||||
if (wc_AsconHash256_Update(&ctx, data, sizeof(data)) != 0)
|
||||
// handle error
|
||||
if (wc_AsconHash256_Final(&ctx, hash, sizeof(hash)) != 0)
|
||||
// handle error
|
||||
// hash contains the final hash
|
||||
\endcode
|
||||
|
||||
\sa wc_AsconHash256_Init
|
||||
\sa wc_AsconHash256_Update
|
||||
*/
|
||||
int wc_AsconHash256_Final(wc_AsconHash256* a, byte* hash);
|
||||
|
||||
/*!
|
||||
\ingroup ASCON
|
||||
\brief This function allocates and initializes a new Ascon AEAD context.
|
||||
|
||||
\return pointer to the newly allocated Ascon AEAD context
|
||||
\return NULL on failure.
|
||||
|
||||
_Example_
|
||||
\code
|
||||
wc_AsconAEAD128* a = wc_AsconAEAD128_New();
|
||||
if (a == NULL) {
|
||||
// handle allocation error
|
||||
}
|
||||
wc_AsconAEAD128_Free(a);
|
||||
\endcode
|
||||
|
||||
\sa wc_AsconAEAD128_Free
|
||||
*/
|
||||
wc_AsconAEAD128* wc_AsconAEAD128_New(void);
|
||||
|
||||
/*!
|
||||
\ingroup ASCON
|
||||
\brief This function frees the resources associated with the Ascon AEAD
|
||||
context.
|
||||
|
||||
\param a pointer to the Ascon AEAD context to free.
|
||||
|
||||
_Example_
|
||||
\code
|
||||
wc_AsconAEAD128* a = wc_AsconAEAD128_New();
|
||||
if (a == NULL) {
|
||||
// handle allocation error
|
||||
}
|
||||
// Use the context
|
||||
wc_AsconAEAD128_Free(a);
|
||||
\endcode
|
||||
|
||||
\sa wc_AsconAEAD128_New
|
||||
*/
|
||||
void wc_AsconAEAD128_Free(wc_AsconAEAD128 *a);
|
||||
|
||||
|
||||
/*!
|
||||
\ingroup ASCON
|
||||
\brief This function initializes an Ascon AEAD context.
|
||||
|
||||
\return 0 on success.
|
||||
\return BAD_FUNC_ARG if the context or output pointer is NULL.
|
||||
|
||||
\param a pointer to the Ascon AEAD context to initialize.
|
||||
|
||||
_Example_
|
||||
\code
|
||||
AsconAead a;
|
||||
|
||||
if (wc_AsconAEAD128_Init(&a) != 0)
|
||||
// handle error
|
||||
\endcode
|
||||
|
||||
\sa wc_AsconAeadEncrypt
|
||||
\sa wc_AsconAeadDecrypt
|
||||
*/
|
||||
int wc_AsconAEAD128_Init(wc_AsconAEAD128* a);
|
||||
|
||||
/*!
|
||||
\ingroup ASCON
|
||||
\brief This function deinitializes an Ascon AEAD context. It does not
|
||||
free the context.
|
||||
|
||||
\param a pointer to the Ascon AEAD context to deinitialize.
|
||||
|
||||
_Example_
|
||||
\code
|
||||
AsconAead a;
|
||||
|
||||
if (wc_AsconAEAD128_Init(&a) != 0)
|
||||
// handle error
|
||||
wc_AsconAEAD128_Clear(&a);
|
||||
\endcode
|
||||
|
||||
\sa wc_AsconAeadEncrypt
|
||||
\sa wc_AsconAeadDecrypt
|
||||
*/
|
||||
void wc_AsconAEAD128_Clear(wc_AsconAEAD128 *a);
|
||||
|
||||
/*!
|
||||
\ingroup ASCON
|
||||
\brief This function sets the key for the Ascon AEAD context.
|
||||
|
||||
\return 0 on success.
|
||||
\return BAD_FUNC_ARG if the context or key pointer is NULL.
|
||||
\return BAD_STATE_E if the key has already been set.
|
||||
|
||||
\param a pointer to the initialized Ascon AEAD context.
|
||||
\param key pointer to the key buffer of length ASCON_AEAD128_KEY_SZ.
|
||||
|
||||
_Example_
|
||||
\code
|
||||
wc_AsconAEAD128 a;
|
||||
byte key[ASCON_AEAD128_KEY_SZ] = { ... };
|
||||
|
||||
if (wc_AsconAEAD128_Init(&a) != 0)
|
||||
// handle error
|
||||
if (wc_AsconAEAD128_SetKey(&a, key) != 0)
|
||||
// handle error
|
||||
\endcode
|
||||
|
||||
\sa wc_AsconAEAD128_Init
|
||||
\sa wc_AsconAEAD128_SetNonce
|
||||
\sa wc_AsconAEAD128_SetAD
|
||||
*/
|
||||
int wc_AsconAEAD128_SetKey(wc_AsconAEAD128* a, const byte* key);
|
||||
|
||||
/*!
|
||||
\ingroup ASCON
|
||||
\brief This function sets the nonce for the Ascon AEAD context.
|
||||
|
||||
\return 0 on success.
|
||||
\return BAD_FUNC_ARG if the context or nonce pointer is NULL.
|
||||
\return BAD_STATE_E if the nonce has already been set.
|
||||
|
||||
\param a pointer to the initialized Ascon AEAD context.
|
||||
\param nonce pointer to the nonce buffer of length ASCON_AEAD128_NONCE_SZ.
|
||||
|
||||
_Example_
|
||||
\code
|
||||
wc_AsconAEAD128 a;
|
||||
byte nonce[ASCON_AEAD128_NONCE_SZ] = { ... };
|
||||
|
||||
if (wc_AsconAEAD128_Init(&a) != 0)
|
||||
// handle error
|
||||
if (wc_AsconAEAD128_SetNonce(&a, nonce) != 0)
|
||||
// handle error
|
||||
\endcode
|
||||
|
||||
\sa wc_AsconAEAD128_Init
|
||||
\sa wc_AsconAEAD128_SetKey
|
||||
\sa wc_AsconAEAD128_SetAD
|
||||
*/
|
||||
int wc_AsconAEAD128_SetNonce(wc_AsconAEAD128* a, const byte* nonce);
|
||||
|
||||
/*!
|
||||
\ingroup ASCON
|
||||
\brief This function sets the associated data for the Ascon AEAD context.
|
||||
|
||||
\return 0 on success.
|
||||
\return BAD_FUNC_ARG if the context or associated data pointer is NULL.
|
||||
\return BAD_STATE_E if the key or nonce has not been set.
|
||||
|
||||
\param a pointer to the initialized Ascon AEAD context.
|
||||
\param ad pointer to the associated data buffer.
|
||||
\param adSz size of the associated data buffer.
|
||||
|
||||
_Example_
|
||||
\code
|
||||
wc_AsconAEAD128 a;
|
||||
byte key[ASCON_AEAD128_KEY_SZ] = { ... };
|
||||
byte nonce[ASCON_AEAD128_NONCE_SZ] = { ... };
|
||||
byte ad[] = { ... };
|
||||
|
||||
if (wc_AsconAEAD128_Init(&a) != 0)
|
||||
// handle error
|
||||
if (wc_AsconAEAD128_SetKey(&a, key) != 0)
|
||||
// handle error
|
||||
if (wc_AsconAEAD128_SetNonce(&a, nonce) != 0)
|
||||
// handle error
|
||||
if (wc_AsconAEAD128_SetAD(&a, ad, sizeof(ad)) != 0)
|
||||
// handle error
|
||||
\endcode
|
||||
|
||||
\sa wc_AsconAEAD128_Init
|
||||
\sa wc_AsconAEAD128_SetKey
|
||||
\sa wc_AsconAEAD128_SetNonce
|
||||
*/
|
||||
int wc_AsconAEAD128_SetAD(wc_AsconAEAD128* a, const byte* ad, word32 adSz);
|
||||
|
||||
/*!
|
||||
\ingroup ASCON
|
||||
\brief This function encrypts a plaintext message using Ascon AEAD. The
|
||||
output is stored in the out buffer. The length of the output is
|
||||
equal to the length of the input.
|
||||
|
||||
\return 0 on success.
|
||||
\return BAD_FUNC_ARG if the context or output pointer is NULL or the input
|
||||
is NULL while the input size is greater than 0.
|
||||
\return BAD_STATE_E if the key, nonce, or additional data has not been set
|
||||
or the context was previously used for decryption.
|
||||
|
||||
\param a pointer to the initialized Ascon AEAD context.
|
||||
\param out pointer to the output buffer to store the ciphertext.
|
||||
\param in pointer to the input buffer containing the plaintext message.
|
||||
\param inSz length of the input buffer.
|
||||
|
||||
_Example_
|
||||
\code
|
||||
wc_AsconAEAD128 a;
|
||||
byte key[ASCON_AEAD128_KEY_SZ] = { ... };
|
||||
byte nonce[ASCON_AEAD128_NONCE_SZ] = { ... };
|
||||
byte plaintext[PLAIN_TEXT_SIZE] = { ... };
|
||||
byte ciphertext[CIPHER_TEXT_SIZE];
|
||||
byte tag[ASCON_AEAD128_TAG_SZ] = { ... };
|
||||
|
||||
if (wc_AsconAeadInit(&a) != 0)
|
||||
// handle error
|
||||
if (wc_AsconAEAD128_SetKey(&a, key) != 0)
|
||||
// handle error
|
||||
if (wc_AsconAEAD128_SetNonce(&a, nonce) != 0)
|
||||
// handle error
|
||||
if (wc_AsconAEAD128_SetAD(&a, ad, sizeof(ad)) != 0)
|
||||
// handle error
|
||||
if (wc_AsconAEAD128_EncryptUpdate(&a, ciphertext, plaintext,
|
||||
sizeof(plaintext)) != 0)
|
||||
// handle error
|
||||
if (wc_AsconAEAD128_EncryptFinal(&a, tag) != 0)
|
||||
// handle error
|
||||
\endcode
|
||||
|
||||
\sa wc_AsconAeadInit
|
||||
\sa wc_AsconAEAD128_Clear
|
||||
\sa wc_AsconAEAD128_SetKey
|
||||
\sa wc_AsconAEAD128_SetNonce
|
||||
\sa wc_AsconAEAD128_SetAD
|
||||
\sa wc_AsconAEAD128_EncryptFinal
|
||||
\sa wc_AsconAEAD128_DecryptUpdate
|
||||
\sa wc_AsconAEAD128_DecryptFinal
|
||||
*/
|
||||
int wc_AsconAEAD128_EncryptUpdate(wc_AsconAEAD128* a, byte* out, const byte* in,
|
||||
word32 inSz);
|
||||
|
||||
/*!
|
||||
\ingroup ASCON
|
||||
\brief This function finalizes the encryption process using Ascon AEAD and
|
||||
produces the authentication tag.
|
||||
|
||||
\return 0 on success.
|
||||
\return BAD_FUNC_ARG if the context or output pointer is NULL or the input
|
||||
is NULL while the input size is greater than 0.
|
||||
\return BAD_STATE_E if the key, nonce, or additional data has not been set
|
||||
or the context was previously used for decryption.
|
||||
|
||||
\param a pointer to the initialized Ascon AEAD context.
|
||||
\param tag pointer to the output buffer to store the authentication tag.
|
||||
|
||||
_Example_
|
||||
\code
|
||||
wc_AsconAEAD128 a;
|
||||
byte key[ASCON_AEAD128_KEY_SZ] = { ... };
|
||||
byte nonce[ASCON_AEAD128_NONCE_SZ] = { ... };
|
||||
byte plaintext[PLAIN_TEXT_SIZE] = { ... };
|
||||
byte ciphertext[CIPHER_TEXT_SIZE];
|
||||
byte tag[ASCON_AEAD128_TAG_SZ] = { ... };
|
||||
|
||||
if (wc_AsconAeadInit(&a) != 0)
|
||||
// handle error
|
||||
if (wc_AsconAEAD128_SetKey(&a, key) != 0)
|
||||
// handle error
|
||||
if (wc_AsconAEAD128_SetNonce(&a, nonce) != 0)
|
||||
// handle error
|
||||
if (wc_AsconAEAD128_SetAD(&a, ad, sizeof(ad)) != 0)
|
||||
// handle error
|
||||
if (wc_AsconAEAD128_EncryptUpdate(&a, ciphertext, plaintext,
|
||||
sizeof(plaintext)) != 0)
|
||||
// handle error
|
||||
if (wc_AsconAEAD128_EncryptFinal(&a, tag) != 0)
|
||||
// handle error
|
||||
\endcode
|
||||
|
||||
\sa wc_AsconAEAD128_Init
|
||||
\sa wc_AsconAEAD128_SetKey
|
||||
\sa wc_AsconAEAD128_SetNonce
|
||||
\sa wc_AsconAEAD128_SetAD
|
||||
\sa wc_AsconAEAD128_EncryptUpdate
|
||||
\sa wc_AsconAEAD128_DecryptUpdate
|
||||
\sa wc_AsconAEAD128_DecryptFinal
|
||||
*/
|
||||
int wc_AsconAEAD128_EncryptFinal(wc_AsconAEAD128* a, byte* tag);
|
||||
|
||||
/*!
|
||||
\ingroup ASCON
|
||||
\brief This function updates the decryption process using Ascon AEAD. The
|
||||
output is stored in the out buffer. The length of the output is
|
||||
equal to the length of the input.
|
||||
|
||||
\return 0 on success.
|
||||
\return BAD_FUNC_ARG if the context or output pointer is NULL or the input
|
||||
is NULL while the input size is greater than 0.
|
||||
\return BAD_STATE_E if the key, nonce, or additional data has not been set
|
||||
or the context was previously used for encryption.
|
||||
|
||||
\param a pointer to the initialized Ascon AEAD context.
|
||||
\param out pointer to the output buffer to store the plaintext.
|
||||
\param in pointer to the input buffer containing the ciphertext message.
|
||||
\param inSz length of the input buffer.
|
||||
|
||||
_Example_
|
||||
\code
|
||||
wc_AsconAEAD128 a;
|
||||
byte key[ASCON_AEAD128_KEY_SZ] = { ... };
|
||||
byte nonce[ASCON_AEAD128_NONCE_SZ] = { ... };
|
||||
byte ciphertext[CIPHER_TEXT_SIZE] = { ... };
|
||||
byte plaintext[PLAIN_TEXT_SIZE];
|
||||
byte tag[ASCON_AEAD128_TAG_SZ] = { ... };
|
||||
|
||||
if (wc_AsconAeadInit(&a) != 0)
|
||||
// handle error
|
||||
if (wc_AsconAEAD128_SetKey(&a, key) != 0)
|
||||
// handle error
|
||||
if (wc_AsconAEAD128_SetNonce(&a, nonce) != 0)
|
||||
// handle error
|
||||
if (wc_AsconAEAD128_SetAD(&a, ad, sizeof(ad)) != 0)
|
||||
// handle error
|
||||
if (wc_AsconAEAD128_DecryptUpdate(&a, plaintext, ciphertext,
|
||||
sizeof(ciphertext)) != 0)
|
||||
// handle error
|
||||
if (wc_AsconAEAD128_DecryptFinal(&a, tag) != 0)
|
||||
// handle error
|
||||
\endcode
|
||||
|
||||
\sa wc_AsconAEAD128_Init
|
||||
\sa wc_AsconAEAD128_SetKey
|
||||
\sa wc_AsconAEAD128_SetNonce
|
||||
\sa wc_AsconAEAD128_SetAD
|
||||
\sa wc_AsconAEAD128_EncryptUpdate
|
||||
\sa wc_AsconAEAD128_EncryptFinal
|
||||
\sa wc_AsconAEAD128_DecryptFinal
|
||||
*/
|
||||
int wc_AsconAEAD128_DecryptUpdate(wc_AsconAEAD128* a, byte* out, const byte* in,
|
||||
word32 inSz);
|
||||
|
||||
/*!
|
||||
\ingroup ASCON
|
||||
\brief This function finalizes the decryption process using Ascon AEAD and
|
||||
verifies the authentication tag.
|
||||
|
||||
\return 0 on success.
|
||||
\return BAD_FUNC_ARG if the context or tag pointer is NULL.
|
||||
\return BAD_STATE_E if the key, nonce, or additional data has not been set
|
||||
or the context was previously used for encryption.
|
||||
\return ASCON_AUTH_E if the authentication tag does not match.
|
||||
|
||||
\param a pointer to the initialized Ascon AEAD context.
|
||||
\param tag pointer to the buffer containing the authentication tag to verify
|
||||
|
||||
_Example_
|
||||
\code
|
||||
wc_AsconAEAD128 a;
|
||||
byte key[ASCON_AEAD128_KEY_SZ] = { ... };
|
||||
byte nonce[ASCON_AEAD128_NONCE_SZ] = { ... };
|
||||
byte ciphertext[CIPHER_TEXT_SIZE] = { ... };
|
||||
byte plaintext[PLAIN_TEXT_SIZE];
|
||||
byte tag[ASCON_AEAD128_TAG_SZ] = { ... };
|
||||
|
||||
if (wc_AsconAeadInit(&a) != 0)
|
||||
// handle error
|
||||
if (wc_AsconAEAD128_SetKey(&a, key) != 0)
|
||||
// handle error
|
||||
if (wc_AsconAEAD128_SetNonce(&a, nonce) != 0)
|
||||
// handle error
|
||||
if (wc_AsconAEAD128_SetAD(&a, ad, sizeof(ad)) != 0)
|
||||
// handle error
|
||||
if (wc_AsconAEAD128_DecryptUpdate(&a, plaintext, ciphertext,
|
||||
sizeof(ciphertext)) != 0)
|
||||
// handle error
|
||||
if (wc_AsconAEAD128_DecryptFinal(&a, tag) != 0)
|
||||
// handle error
|
||||
\endcode
|
||||
|
||||
\sa wc_AsconAEAD128_Init
|
||||
\sa wc_AsconAEAD128_SetKey
|
||||
\sa wc_AsconAEAD128_SetNonce
|
||||
\sa wc_AsconAEAD128_SetAD
|
||||
\sa wc_AsconAEAD128_DecryptUpdate
|
||||
\sa wc_AsconAEAD128_EncryptUpdate
|
||||
\sa wc_AsconAEAD128_EncryptFinal
|
||||
*/
|
||||
int wc_AsconAEAD128_DecryptFinal(wc_AsconAEAD128* a, const byte* tag);
|
||||
|
||||
|
@ -1164,6 +1164,10 @@ src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/chacha20_poly1305.c
|
||||
endif BUILD_POLY1305
|
||||
endif BUILD_CHACHA
|
||||
|
||||
if BUILD_ASCON
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/ascon.c
|
||||
endif
|
||||
|
||||
if !BUILD_INLINE
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/misc.c
|
||||
endif
|
||||
|
@ -286,7 +286,8 @@
|
||||
#define WOLFSSL_MISC_INCLUDED
|
||||
#include <wolfcrypt/src/misc.c>
|
||||
|
||||
|
||||
/* Gather test declarations to include them in the testCases array */
|
||||
#include <tests/api/ascon.h>
|
||||
|
||||
#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_TLS) && \
|
||||
!defined(NO_RSA) && !defined(SINGLE_THREADED) && \
|
||||
@ -101723,6 +101724,10 @@ TEST_CASE testCases[] = {
|
||||
TEST_DECL(test_wc_dilithium_sig_kats),
|
||||
TEST_DECL(test_wc_dilithium_verify_kats),
|
||||
|
||||
/* Ascon */
|
||||
TEST_DECL(test_ascon_hash256),
|
||||
TEST_DECL(test_ascon_aead128),
|
||||
|
||||
/* Signature API */
|
||||
TEST_DECL(test_wc_SignatureGetSize_ecc),
|
||||
TEST_DECL(test_wc_SignatureGetSize_rsa),
|
||||
|
6674
tests/api/ascon.c
Normal file
6674
tests/api/ascon.c
Normal file
File diff suppressed because it is too large
Load Diff
28
tests/api/ascon.h
Normal file
28
tests/api/ascon.h
Normal file
@ -0,0 +1,28 @@
|
||||
/* ascon.h
|
||||
*
|
||||
* Copyright (C) 2006-2025 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfSSL.
|
||||
*
|
||||
* wolfSSL is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfSSL is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
#ifndef WOLFCRYPT_TEST_ASCON_H
|
||||
#define WOLFCRYPT_TEST_ASCON_H
|
||||
|
||||
int test_ascon_hash256(void);
|
||||
int test_ascon_aead128(void);
|
||||
|
||||
#endif /* WOLFCRYPT_TEST_ASCON_H */
|
4
tests/api/include.am
Normal file
4
tests/api/include.am
Normal file
@ -0,0 +1,4 @@
|
||||
if BUILD_TESTS
|
||||
tests_unit_test_SOURCES += tests/api/ascon.c
|
||||
endif
|
||||
EXTRA_DIST += tests/api/ascon.h
|
@ -18,6 +18,7 @@ tests_unit_test_SOURCES = \
|
||||
tests_unit_test_CFLAGS = -DNO_MAIN_DRIVER $(AM_CFLAGS) $(WOLFSENTRY_INCLUDE)
|
||||
tests_unit_test_LDADD = src/libwolfssl@LIBSUFFIX@.la $(LIB_STATIC_ADD) $(WOLFSENTRY_LIB)
|
||||
tests_unit_test_DEPENDENCIES = src/libwolfssl@LIBSUFFIX@.la
|
||||
include tests/api/include.am
|
||||
endif
|
||||
EXTRA_DIST += tests/unit.h \
|
||||
tests/test.conf \
|
||||
|
@ -553,6 +553,10 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ASCON
|
||||
#include <wolfssl/wolfcrypt/ascon.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FIPS
|
||||
#include <wolfssl/wolfcrypt/fips_test.h>
|
||||
|
||||
@ -669,6 +673,8 @@
|
||||
#define BENCH_BLAKE2B 0x00008000
|
||||
#define BENCH_BLAKE2S 0x00010000
|
||||
#define BENCH_SM3 0x00020000
|
||||
#define BENCH_ASCON_HASH256 0x00040000
|
||||
#define BENCH_ASCON_AEAD128 0x00080000
|
||||
|
||||
/* MAC algorithms. */
|
||||
#define BENCH_CMAC 0x00000001
|
||||
@ -882,6 +888,9 @@ static const bench_alg bench_cipher_opt[] = {
|
||||
#endif
|
||||
#ifndef NO_DES3
|
||||
{ "-des", BENCH_DES },
|
||||
#endif
|
||||
#ifdef HAVE_ASCON
|
||||
{ "-ascon-aead", BENCH_ASCON_AEAD128 },
|
||||
#endif
|
||||
{ NULL, 0 }
|
||||
};
|
||||
@ -949,6 +958,9 @@ static const bench_alg bench_digest_opt[] = {
|
||||
#endif
|
||||
#ifdef HAVE_BLAKE2S
|
||||
{ "-blake2s", BENCH_BLAKE2S },
|
||||
#endif
|
||||
#ifdef HAVE_ASCON
|
||||
{ "-ascon-hash", BENCH_ASCON_HASH256 },
|
||||
#endif
|
||||
{ NULL, 0 }
|
||||
};
|
||||
@ -3342,6 +3354,10 @@ static void* benchmarks_do(void* args)
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_ASCON
|
||||
if (bench_all || (bench_cipher_algs & BENCH_ASCON_AEAD128))
|
||||
bench_ascon_aead();
|
||||
#endif
|
||||
#ifndef NO_MD5
|
||||
if (bench_all || (bench_digest_algs & BENCH_MD5)) {
|
||||
#ifndef NO_SW_BENCH
|
||||
@ -3515,6 +3531,10 @@ static void* benchmarks_do(void* args)
|
||||
if (bench_all || (bench_digest_algs & BENCH_BLAKE2S))
|
||||
bench_blake2s();
|
||||
#endif
|
||||
#ifdef HAVE_ASCON
|
||||
if (bench_all || (bench_digest_algs & BENCH_ASCON_HASH256))
|
||||
bench_ascon_hash();
|
||||
#endif
|
||||
#ifdef WOLFSSL_CMAC
|
||||
if (bench_all || (bench_mac_algs & BENCH_CMAC)) {
|
||||
bench_cmac(0);
|
||||
@ -6103,6 +6123,67 @@ exit:
|
||||
}
|
||||
#endif /* HAVE_CHACHA && HAVE_POLY1305 */
|
||||
|
||||
#ifdef HAVE_ASCON
|
||||
|
||||
void bench_ascon_aead(void)
|
||||
{
|
||||
#define ASCON_AD (byte*)"ADADADADAD"
|
||||
#define ASCON_AD_SZ XSTR_SIZEOF(ASCON_AD)
|
||||
double start;
|
||||
int ret = 0, i, count;
|
||||
WC_DECLARE_VAR(authTag, byte, ASCON_AEAD128_TAG_SZ, HEAP_HINT);
|
||||
WC_DECLARE_VAR(enc, wc_AsconAEAD128, 1, HEAP_HINT);
|
||||
DECLARE_MULTI_VALUE_STATS_VARS()
|
||||
|
||||
WC_ALLOC_VAR(authTag, byte, ASCON_AEAD128_TAG_SZ, HEAP_HINT);
|
||||
XMEMSET(authTag, 0, ASCON_AEAD128_TAG_SZ);
|
||||
|
||||
WC_ALLOC_VAR(enc, wc_AsconAEAD128, 1, HEAP_HINT);
|
||||
XMEMSET(enc, 0, sizeof(wc_AsconAEAD128));
|
||||
|
||||
bench_stats_start(&count, &start);
|
||||
do {
|
||||
for (i = 0; i < numBlocks; i++) {
|
||||
ret = wc_AsconAEAD128_Init(enc);
|
||||
if (ret == 0)
|
||||
ret = wc_AsconAEAD128_SetKey(enc, bench_key);
|
||||
if (ret == 0)
|
||||
ret = wc_AsconAEAD128_SetNonce(enc, bench_iv);
|
||||
if (ret == 0)
|
||||
ret = wc_AsconAEAD128_SetAD(enc, ASCON_AD, ASCON_AD_SZ);
|
||||
if (ret == 0) {
|
||||
ret = wc_AsconAEAD128_EncryptUpdate(enc, bench_cipher,
|
||||
bench_plain, bench_size);
|
||||
}
|
||||
if (ret == 0)
|
||||
ret = wc_AsconAEAD128_EncryptFinal(enc, authTag);
|
||||
wc_AsconAEAD128_Clear(enc);
|
||||
|
||||
if (ret != 0) {
|
||||
printf("ASCON-AEAD error: %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
RECORD_MULTI_VALUE_STATS();
|
||||
}
|
||||
count += i;
|
||||
} while (bench_stats_check(start)
|
||||
#ifdef MULTI_VALUE_STATISTICS
|
||||
|| runs < minimum_runs
|
||||
#endif
|
||||
);
|
||||
|
||||
bench_stats_sym_finish("ASCON-AEAD", 0, count, bench_size, start, ret);
|
||||
#ifdef MULTI_VALUE_STATISTICS
|
||||
bench_multi_value_stats(max, min, sum, squareSum, runs);
|
||||
#endif
|
||||
|
||||
exit:
|
||||
|
||||
WC_FREE_VAR(authTag, HEAP_HINT);
|
||||
WC_FREE_VAR(enc, HEAP_HINT);
|
||||
}
|
||||
|
||||
#endif /* HAVE_ASCON */
|
||||
|
||||
#ifndef NO_MD5
|
||||
void bench_md5(int useDeviceID)
|
||||
@ -7996,6 +8077,64 @@ void bench_blake2s(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ASCON
|
||||
void bench_ascon_hash(void)
|
||||
{
|
||||
wc_AsconHash256 ascon;
|
||||
byte digest[ASCON_HASH256_SZ];
|
||||
double start;
|
||||
int ret = 0, i, count;
|
||||
|
||||
if (digest_stream) {
|
||||
ret = wc_AsconHash256_Init(&ascon);
|
||||
if (ret != 0) {
|
||||
printf("wc_AsconHash256_Init failed, ret = %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
bench_stats_start(&count, &start);
|
||||
do {
|
||||
for (i = 0; i < numBlocks; i++) {
|
||||
ret = wc_AsconHash256_Update(&ascon, bench_plain, bench_size);
|
||||
if (ret != 0) {
|
||||
printf("wc_AsconHash256_Update failed, ret = %d\n", ret);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ret = wc_AsconHash256_Final(&ascon, digest);
|
||||
if (ret != 0) {
|
||||
printf("wc_AsconHash256_Final failed, ret = %d\n", ret);
|
||||
return;
|
||||
}
|
||||
count += i;
|
||||
} while (bench_stats_check(start));
|
||||
}
|
||||
else {
|
||||
bench_stats_start(&count, &start);
|
||||
do {
|
||||
for (i = 0; i < numBlocks; i++) {
|
||||
ret = wc_AsconHash256_Init(&ascon);
|
||||
if (ret != 0) {
|
||||
printf("wc_AsconHash256_Init failed, ret = %d\n", ret);
|
||||
return;
|
||||
}
|
||||
ret = wc_AsconHash256_Update(&ascon, bench_plain, bench_size);
|
||||
if (ret != 0) {
|
||||
printf("wc_AsconHash256_Update failed, ret = %d\n", ret);
|
||||
return;
|
||||
}
|
||||
ret = wc_AsconHash256_Final(&ascon, digest);
|
||||
if (ret != 0) {
|
||||
printf("wc_AsconHash256_Final failed, ret = %d\n", ret);
|
||||
return;
|
||||
}
|
||||
}
|
||||
count += i;
|
||||
} while (bench_stats_check(start));
|
||||
}
|
||||
bench_stats_sym_finish("ASCON hash", 0, count, bench_size, start, ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_CMAC
|
||||
|
||||
|
@ -64,6 +64,7 @@ void bench_camellia(void);
|
||||
void bench_sm4_cbc(void);
|
||||
void bench_sm4_gcm(void);
|
||||
void bench_sm4_ccm(void);
|
||||
void bench_ascon_aead(void);
|
||||
void bench_md5(int useDeviceID);
|
||||
void bench_sha(int useDeviceID);
|
||||
void bench_sha224(int useDeviceID);
|
||||
@ -128,6 +129,7 @@ void bench_sakke(void);
|
||||
void bench_rng(void);
|
||||
void bench_blake2b(void);
|
||||
void bench_blake2s(void);
|
||||
void bench_ascon_hash(void);
|
||||
void bench_pbkdf2(void);
|
||||
void bench_falconKeySign(byte level);
|
||||
void bench_dilithiumKeySign(byte level);
|
||||
|
527
wolfcrypt/src/ascon.c
Normal file
527
wolfcrypt/src/ascon.c
Normal file
@ -0,0 +1,527 @@
|
||||
/* ascon.c
|
||||
*
|
||||
* Copyright (C) 2006-2025 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfSSL.
|
||||
*
|
||||
* wolfSSL is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfSSL is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <wolfssl/wolfcrypt/settings.h>
|
||||
|
||||
#ifdef HAVE_ASCON
|
||||
|
||||
#include <wolfssl/wolfcrypt/ascon.h>
|
||||
#include <wolfssl/wolfcrypt/error-crypt.h>
|
||||
#include <wolfssl/wolfcrypt/logging.h>
|
||||
#ifdef NO_INLINE
|
||||
#include <wolfssl/wolfcrypt/misc.h>
|
||||
#else
|
||||
#define WOLFSSL_MISC_INCLUDED
|
||||
#include <wolfcrypt/src/misc.c>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Implementation of the ASCON AEAD and HASH algorithms. Based on the NIST
|
||||
* Initial Public Draft "NIST SP 800-232 ipd" and reference implementation found
|
||||
* at https://github.com/ascon/ascon-c.
|
||||
*/
|
||||
|
||||
/*
|
||||
* TODO
|
||||
* - Add support for big-endian systems
|
||||
* - Add support for 32-bit and smaller systems */
|
||||
|
||||
#ifndef WORD64_AVAILABLE
|
||||
#error "Ascon implementation requires a 64-bit word"
|
||||
#endif
|
||||
|
||||
/* Data block size in bytes */
|
||||
#define ASCON_HASH256_RATE 8
|
||||
#define ASCON_HASH256_ROUNDS 12
|
||||
#define ASCON_HASH256_IV 0x0000080100CC0002ULL
|
||||
|
||||
#define ASCON_AEAD128_ROUNDS_PA 12
|
||||
#define ASCON_AEAD128_ROUNDS_PB 8
|
||||
#define ASCON_AEAD128_IV 0x00001000808C0001ULL
|
||||
#define ASCON_AEAD128_RATE 16
|
||||
|
||||
#define MAX_ROUNDS 12
|
||||
|
||||
#ifndef WOLFSSL_ASCON_UNROLL
|
||||
|
||||
/* Table 5 */
|
||||
static const byte round_constants[MAX_ROUNDS] = {
|
||||
0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87, 0x78, 0x69, 0x5a, 0x4b
|
||||
};
|
||||
|
||||
static byte start_index(byte rounds)
|
||||
{
|
||||
switch (rounds) {
|
||||
case 8:
|
||||
return 4;
|
||||
case 12:
|
||||
return 0;
|
||||
default:
|
||||
WOLFSSL_MSG("Something went wrong in wolfCrypt logic. Wrong ASCON "
|
||||
"rounds value.");
|
||||
return MAX_ROUNDS;
|
||||
}
|
||||
}
|
||||
|
||||
static WC_INLINE void ascon_round(AsconState* a, byte round)
|
||||
{
|
||||
word64 tmp0, tmp1, tmp2, tmp3, tmp4;
|
||||
/* 3.2 Constant-Addition Layer */
|
||||
a->s64[2] ^= round_constants[round];
|
||||
/* 3.3 Substitution Layer */
|
||||
a->s64[0] ^= a->s64[4];
|
||||
a->s64[4] ^= a->s64[3];
|
||||
a->s64[2] ^= a->s64[1];
|
||||
tmp0 = a->s64[0] ^ (~a->s64[1] & a->s64[2]);
|
||||
tmp2 = a->s64[2] ^ (~a->s64[3] & a->s64[4]);
|
||||
tmp4 = a->s64[4] ^ (~a->s64[0] & a->s64[1]);
|
||||
tmp1 = a->s64[1] ^ (~a->s64[2] & a->s64[3]);
|
||||
tmp3 = a->s64[3] ^ (~a->s64[4] & a->s64[0]);
|
||||
tmp1 ^= tmp0;
|
||||
tmp3 ^= tmp2;
|
||||
tmp0 ^= tmp4;
|
||||
tmp2 = ~tmp2;
|
||||
/* 3.4 Linear Diffusion Layer */
|
||||
a->s64[4] = tmp4 ^ rotrFixed64(tmp4, 7) ^ rotrFixed64(tmp4, 41);
|
||||
a->s64[1] = tmp1 ^ rotrFixed64(tmp1, 61) ^ rotrFixed64(tmp1, 39);
|
||||
a->s64[3] = tmp3 ^ rotrFixed64(tmp3, 10) ^ rotrFixed64(tmp3, 17);
|
||||
a->s64[0] = tmp0 ^ rotrFixed64(tmp0, 19) ^ rotrFixed64(tmp0, 28);
|
||||
a->s64[2] = tmp2 ^ rotrFixed64(tmp2, 1) ^ rotrFixed64(tmp2, 6);
|
||||
}
|
||||
|
||||
static void permutation(AsconState* a, byte rounds)
|
||||
{
|
||||
byte i = start_index(rounds);
|
||||
for (; i < MAX_ROUNDS; i++) {
|
||||
ascon_round(a, i);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define p(a, c) do { \
|
||||
word64 tmp0, tmp1, tmp2, tmp3, tmp4; \
|
||||
/* 3.2 Constant-Addition Layer */ \
|
||||
(a)->s64[2] ^= c; \
|
||||
/* 3.3 Substitution Layer */ \
|
||||
(a)->s64[0] ^= (a)->s64[4]; \
|
||||
(a)->s64[4] ^= (a)->s64[3]; \
|
||||
(a)->s64[2] ^= (a)->s64[1]; \
|
||||
tmp0 = (a)->s64[0] ^ (~(a)->s64[1] & (a)->s64[2]); \
|
||||
tmp2 = (a)->s64[2] ^ (~(a)->s64[3] & (a)->s64[4]); \
|
||||
tmp4 = (a)->s64[4] ^ (~(a)->s64[0] & (a)->s64[1]); \
|
||||
tmp1 = (a)->s64[1] ^ (~(a)->s64[2] & (a)->s64[3]); \
|
||||
tmp3 = (a)->s64[3] ^ (~(a)->s64[4] & (a)->s64[0]); \
|
||||
tmp1 ^= tmp0; \
|
||||
tmp3 ^= tmp2; \
|
||||
tmp0 ^= tmp4; \
|
||||
tmp2 = ~tmp2; \
|
||||
/* 3.4 Linear Diffusion Layer */ \
|
||||
(a)->s64[4] = tmp4 ^ rotrFixed64(tmp4, 7) ^ rotrFixed64(tmp4, 41); \
|
||||
(a)->s64[1] = tmp1 ^ rotrFixed64(tmp1, 61) ^ rotrFixed64(tmp1, 39); \
|
||||
(a)->s64[3] = tmp3 ^ rotrFixed64(tmp3, 10) ^ rotrFixed64(tmp3, 17); \
|
||||
(a)->s64[0] = tmp0 ^ rotrFixed64(tmp0, 19) ^ rotrFixed64(tmp0, 28); \
|
||||
(a)->s64[2] = tmp2 ^ rotrFixed64(tmp2, 1) ^ rotrFixed64(tmp2, 6); \
|
||||
} while (0)
|
||||
|
||||
#define p8(a) \
|
||||
p(a, 0xb4); \
|
||||
p(a, 0xa5); \
|
||||
p(a, 0x96); \
|
||||
p(a, 0x87); \
|
||||
p(a, 0x78); \
|
||||
p(a, 0x69); \
|
||||
p(a, 0x5a); \
|
||||
p(a, 0x4b)
|
||||
|
||||
#define p12(a) \
|
||||
p(a, 0xf0); \
|
||||
p(a, 0xe1); \
|
||||
p(a, 0xd2); \
|
||||
p(a, 0xc3); \
|
||||
p8(a)
|
||||
|
||||
/* Needed layer to evaluate the macro values */
|
||||
#define _permutation(a, rounds) \
|
||||
p ## rounds(a)
|
||||
|
||||
#define permutation(a, rounds) \
|
||||
_permutation(a, rounds)
|
||||
|
||||
#endif
|
||||
|
||||
/* AsconHash API */
|
||||
|
||||
wc_AsconHash256* wc_AsconHash256_New(void)
|
||||
{
|
||||
wc_AsconHash256* ret = (wc_AsconHash256*)XMALLOC(sizeof(wc_AsconHash256),
|
||||
NULL, DYNAMIC_TYPE_ASCON);
|
||||
if (ret != NULL) {
|
||||
if (wc_AsconHash256_Init(ret) != 0) {
|
||||
wc_AsconHash256_Free(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void wc_AsconHash256_Free(wc_AsconHash256* a)
|
||||
{
|
||||
if (a != NULL) {
|
||||
wc_AsconHash256_Clear(a);
|
||||
XFREE(a, NULL, DYNAMIC_TYPE_ASCON);
|
||||
}
|
||||
}
|
||||
|
||||
int wc_AsconHash256_Init(wc_AsconHash256* a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
XMEMSET(a, 0, sizeof(*a));
|
||||
|
||||
a->state.s64[0] = ASCON_HASH256_IV;
|
||||
permutation(&a->state, ASCON_HASH256_ROUNDS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wc_AsconHash256_Clear(wc_AsconHash256* a)
|
||||
{
|
||||
if (a != NULL) {
|
||||
ForceZero(a, sizeof(*a));
|
||||
}
|
||||
}
|
||||
|
||||
int wc_AsconHash256_Update(wc_AsconHash256* a, const byte* data, word32 dataSz)
|
||||
{
|
||||
if (a == NULL || (data == NULL && dataSz != 0))
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (dataSz == 0)
|
||||
return 0;
|
||||
|
||||
/* Process leftover block */
|
||||
if (a->lastBlkSz != 0) {
|
||||
word32 toProcess = min(ASCON_HASH256_RATE - a->lastBlkSz, dataSz);
|
||||
xorbuf(a->state.s8 + a->lastBlkSz, data, toProcess);
|
||||
data += toProcess;
|
||||
dataSz -= toProcess;
|
||||
a->lastBlkSz += toProcess;
|
||||
|
||||
if (a->lastBlkSz < ASCON_HASH256_RATE)
|
||||
return 0;
|
||||
|
||||
permutation(&a->state, ASCON_HASH256_ROUNDS);
|
||||
/* Reset the counter */
|
||||
a->lastBlkSz = 0;
|
||||
}
|
||||
|
||||
while (dataSz >= ASCON_HASH256_RATE) {
|
||||
/* Read in input as little endian numbers */
|
||||
xorbuf(a->state.s64, data, ASCON_HASH256_RATE);
|
||||
permutation(&a->state, ASCON_HASH256_ROUNDS);
|
||||
data += ASCON_HASH256_RATE;
|
||||
dataSz -= ASCON_HASH256_RATE;
|
||||
}
|
||||
|
||||
xorbuf(a->state.s64, data, dataSz);
|
||||
a->lastBlkSz = dataSz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wc_AsconHash256_Final(wc_AsconHash256* a, byte* hash)
|
||||
{
|
||||
byte i;
|
||||
|
||||
if (a == NULL || hash == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
/* Process last block */
|
||||
a->state.s8[a->lastBlkSz] ^= 1;
|
||||
|
||||
for (i = 0; i < ASCON_HASH256_SZ; i += ASCON_HASH256_RATE) {
|
||||
permutation(&a->state, ASCON_HASH256_ROUNDS);
|
||||
XMEMCPY(hash, a->state.s64, ASCON_HASH256_RATE);
|
||||
hash += ASCON_HASH256_RATE;
|
||||
}
|
||||
|
||||
/* Clear state as soon as possible */
|
||||
wc_AsconHash256_Clear(a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* AsconAEAD API */
|
||||
|
||||
wc_AsconAEAD128* wc_AsconAEAD128_New(void)
|
||||
{
|
||||
wc_AsconAEAD128 *ret = (wc_AsconAEAD128*) XMALLOC(sizeof(wc_AsconAEAD128),
|
||||
NULL, DYNAMIC_TYPE_ASCON);
|
||||
if (ret != NULL) {
|
||||
if (wc_AsconAEAD128_Init(ret) != 0) {
|
||||
wc_AsconAEAD128_Free(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void wc_AsconAEAD128_Free(wc_AsconAEAD128 *a)
|
||||
{
|
||||
if (a != NULL) {
|
||||
wc_AsconAEAD128_Clear(a);
|
||||
XFREE(a, NULL, DYNAMIC_TYPE_ASCON);
|
||||
}
|
||||
}
|
||||
|
||||
int wc_AsconAEAD128_Init(wc_AsconAEAD128 *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
XMEMSET(a, 0, sizeof(*a));
|
||||
a->state.s64[0] = ASCON_AEAD128_IV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wc_AsconAEAD128_Clear(wc_AsconAEAD128 *a)
|
||||
{
|
||||
if (a != NULL) {
|
||||
ForceZero(a, sizeof(*a));
|
||||
}
|
||||
}
|
||||
|
||||
int wc_AsconAEAD128_SetKey(wc_AsconAEAD128* a, const byte* key)
|
||||
{
|
||||
if (a == NULL || key == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
if (a->keySet)
|
||||
return BAD_STATE_E;
|
||||
|
||||
XMEMCPY(a->key, key, ASCON_AEAD128_KEY_SZ);
|
||||
a->state.s64[1] = a->key[0];
|
||||
a->state.s64[2] = a->key[1];
|
||||
a->keySet = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wc_AsconAEAD128_SetNonce(wc_AsconAEAD128* a, const byte* nonce)
|
||||
{
|
||||
if (a == NULL || nonce == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
if (a->nonceSet)
|
||||
return BAD_STATE_E;
|
||||
|
||||
XMEMCPY(&a->state.s64[3], nonce, ASCON_AEAD128_NONCE_SZ);
|
||||
a->nonceSet = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wc_AsconAEAD128_SetAD(wc_AsconAEAD128* a, const byte* ad,
|
||||
word32 adSz)
|
||||
{
|
||||
if (a == NULL || (ad == NULL && adSz > 0))
|
||||
return BAD_FUNC_ARG;
|
||||
if (!a->keySet || !a->nonceSet) /* key and nonce must be set before */
|
||||
return BAD_STATE_E;
|
||||
|
||||
permutation(&a->state, ASCON_AEAD128_ROUNDS_PA);
|
||||
a->state.s64[3] ^= a->key[0];
|
||||
a->state.s64[4] ^= a->key[1];
|
||||
|
||||
if (adSz > 0) {
|
||||
while (adSz >= ASCON_AEAD128_RATE) {
|
||||
xorbuf(a->state.s64, ad, ASCON_AEAD128_RATE);
|
||||
permutation(&a->state, ASCON_AEAD128_ROUNDS_PB);
|
||||
ad += ASCON_AEAD128_RATE;
|
||||
adSz -= ASCON_AEAD128_RATE;
|
||||
}
|
||||
xorbuf(a->state.s64, ad, adSz);
|
||||
/* Pad the last block */
|
||||
a->state.s8[adSz] ^= 1;
|
||||
permutation(&a->state, ASCON_AEAD128_ROUNDS_PB);
|
||||
}
|
||||
a->state.s64[4] ^= 1ULL << 63;
|
||||
|
||||
a->adSet = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wc_AsconAEAD128_EncryptUpdate(wc_AsconAEAD128* a, byte* out,
|
||||
const byte* in, word32 inSz)
|
||||
{
|
||||
if (a == NULL || (in == NULL && inSz > 0))
|
||||
return BAD_FUNC_ARG;
|
||||
if (!a->keySet || !a->nonceSet || !a->adSet)
|
||||
return BAD_STATE_E;
|
||||
|
||||
if (a->op == ASCON_AEAD128_NOTSET)
|
||||
a->op = ASCON_AEAD128_ENCRYPT;
|
||||
else if (a->op != ASCON_AEAD128_ENCRYPT)
|
||||
return BAD_STATE_E;
|
||||
|
||||
/* Process leftover from last block */
|
||||
if (a->lastBlkSz != 0) {
|
||||
word32 toProcess = min(ASCON_AEAD128_RATE - a->lastBlkSz, inSz);
|
||||
xorbuf(&a->state.s8[a->lastBlkSz], in, toProcess);
|
||||
XMEMCPY(out, &a->state.s8[a->lastBlkSz], toProcess);
|
||||
a->lastBlkSz += toProcess;
|
||||
in += toProcess;
|
||||
out += toProcess;
|
||||
inSz -= toProcess;
|
||||
|
||||
if (a->lastBlkSz < ASCON_AEAD128_RATE)
|
||||
return 0;
|
||||
|
||||
permutation(&a->state, ASCON_AEAD128_ROUNDS_PB);
|
||||
a->lastBlkSz = 0;
|
||||
}
|
||||
|
||||
while (inSz >= ASCON_AEAD128_RATE) {
|
||||
xorbuf(a->state.s64, in, ASCON_AEAD128_RATE);
|
||||
XMEMCPY(out, a->state.s64, ASCON_AEAD128_RATE);
|
||||
permutation(&a->state, ASCON_AEAD128_ROUNDS_PB);
|
||||
in += ASCON_AEAD128_RATE;
|
||||
out += ASCON_AEAD128_RATE;
|
||||
inSz -= ASCON_AEAD128_RATE;
|
||||
}
|
||||
/* Store leftover */
|
||||
xorbuf(a->state.s64, in, inSz);
|
||||
XMEMCPY(out, a->state.s64, inSz);
|
||||
a->lastBlkSz = inSz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int wc_AsconAEAD128_EncryptFinal(wc_AsconAEAD128* a, byte* tag)
|
||||
{
|
||||
if (a == NULL || tag == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
if (!a->keySet || !a->nonceSet || !a->adSet)
|
||||
return BAD_STATE_E;
|
||||
|
||||
if (a->op != ASCON_AEAD128_ENCRYPT)
|
||||
return BAD_STATE_E;
|
||||
|
||||
/* Process leftover from last block */
|
||||
a->state.s8[a->lastBlkSz] ^= 1;
|
||||
|
||||
a->state.s64[2] ^= a->key[0];
|
||||
a->state.s64[3] ^= a->key[1];
|
||||
permutation(&a->state, ASCON_AEAD128_ROUNDS_PA);
|
||||
a->state.s64[3] ^= a->key[0];
|
||||
a->state.s64[4] ^= a->key[1];
|
||||
|
||||
XMEMCPY(tag, &a->state.s64[3], ASCON_AEAD128_TAG_SZ);
|
||||
|
||||
/* Clear state as soon as possible */
|
||||
wc_AsconAEAD128_Clear(a);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int wc_AsconAEAD128_DecryptUpdate(wc_AsconAEAD128* a, byte* out,
|
||||
const byte* in, word32 inSz)
|
||||
{
|
||||
if (a == NULL || (in == NULL && inSz > 0))
|
||||
return BAD_FUNC_ARG;
|
||||
if (!a->keySet || !a->nonceSet || !a->adSet)
|
||||
return BAD_STATE_E;
|
||||
|
||||
if (a->op == ASCON_AEAD128_NOTSET)
|
||||
a->op = ASCON_AEAD128_DECRYPT;
|
||||
else if (a->op != ASCON_AEAD128_DECRYPT)
|
||||
return BAD_STATE_E;
|
||||
|
||||
/* Process leftover block */
|
||||
if (a->lastBlkSz != 0) {
|
||||
word32 toProcess = min(ASCON_AEAD128_RATE - a->lastBlkSz, inSz);
|
||||
xorbufout(out, a->state.s8 + a->lastBlkSz, in, toProcess);
|
||||
XMEMCPY(a->state.s8 + a->lastBlkSz, in, toProcess);
|
||||
in += toProcess;
|
||||
out += toProcess;
|
||||
inSz -= toProcess;
|
||||
a->lastBlkSz += toProcess;
|
||||
|
||||
if (a->lastBlkSz < ASCON_AEAD128_RATE)
|
||||
return 0;
|
||||
|
||||
permutation(&a->state, ASCON_AEAD128_ROUNDS_PB);
|
||||
a->lastBlkSz = 0;
|
||||
}
|
||||
|
||||
while (inSz >= ASCON_AEAD128_RATE) {
|
||||
xorbufout(out, a->state.s64, in, ASCON_AEAD128_RATE);
|
||||
XMEMCPY(a->state.s64, in, ASCON_AEAD128_RATE);
|
||||
permutation(&a->state, ASCON_AEAD128_ROUNDS_PB);
|
||||
in += ASCON_AEAD128_RATE;
|
||||
out += ASCON_AEAD128_RATE;
|
||||
inSz -= ASCON_AEAD128_RATE;
|
||||
}
|
||||
/* Store leftover */
|
||||
xorbufout(out, a->state.s64, in, inSz);
|
||||
XMEMCPY(a->state.s64, in, inSz);
|
||||
a->lastBlkSz = inSz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wc_AsconAEAD128_DecryptFinal(wc_AsconAEAD128* a, const byte* tag)
|
||||
{
|
||||
if (a == NULL || tag == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
if (!a->keySet || !a->nonceSet || !a->adSet)
|
||||
return BAD_STATE_E;
|
||||
|
||||
if (a->op != ASCON_AEAD128_DECRYPT)
|
||||
return BAD_STATE_E;
|
||||
|
||||
/* Pad last block */
|
||||
a->state.s8[a->lastBlkSz] ^= 1;
|
||||
|
||||
a->state.s64[2] ^= a->key[0];
|
||||
a->state.s64[3] ^= a->key[1];
|
||||
permutation(&a->state, ASCON_AEAD128_ROUNDS_PA);
|
||||
a->state.s64[3] ^= a->key[0];
|
||||
a->state.s64[4] ^= a->key[1];
|
||||
|
||||
if (ConstantCompare(tag, (const byte*)&a->state.s64[3],
|
||||
ASCON_AEAD128_TAG_SZ) != 0)
|
||||
return ASCON_AUTH_E;
|
||||
|
||||
/* Clear state as soon as possible */
|
||||
wc_AsconAEAD128_Clear(a);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* HAVE_ASCON */
|
@ -651,6 +651,9 @@ const char* wc_GetErrorString(int error)
|
||||
case DEADLOCK_AVERTED_E:
|
||||
return "Deadlock averted -- retry the call";
|
||||
|
||||
case ASCON_AUTH_E:
|
||||
return "ASCON Authentication check fail";
|
||||
|
||||
case MAX_CODE_E:
|
||||
case WC_SPAN1_MIN_CODE_E:
|
||||
case MIN_CODE_E:
|
||||
|
@ -48,6 +48,13 @@
|
||||
#include <wolfssl/wolfcrypt/wc_port.h>
|
||||
#include <wolfssl/wolfcrypt/mem_track.h>
|
||||
|
||||
#ifdef NO_INLINE
|
||||
#include <wolfssl/wolfcrypt/misc.h>
|
||||
#else
|
||||
#define WOLFSSL_MISC_INCLUDED
|
||||
#include <wolfcrypt/src/misc.c>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_WOLFCRYPT_TEST_OPTIONS)
|
||||
#include <wolfssl/ssl.h>
|
||||
#define err_sys err_sys_remap /* remap err_sys */
|
||||
@ -285,6 +292,7 @@ const byte const_byte_array[] = "A+Gd\0\0\0";
|
||||
#include <wolfssl/wolfcrypt/srp.h>
|
||||
#include <wolfssl/wolfcrypt/chacha.h>
|
||||
#include <wolfssl/wolfcrypt/chacha20_poly1305.h>
|
||||
#include <wolfssl/wolfcrypt/ascon.h>
|
||||
#include <wolfssl/wolfcrypt/pwdbased.h>
|
||||
#include <wolfssl/wolfcrypt/ripemd.h>
|
||||
#include <wolfssl/wolfcrypt/error-crypt.h>
|
||||
@ -590,6 +598,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aes192_test(void);
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aes256_test(void);
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aesofb_test(void);
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cmac_test(void);
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ascon_hash256_test(void);
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ascon_aead128_test(void);
|
||||
#if defined(WOLFSSL_SIPHASH)
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t siphash_test(void);
|
||||
#endif
|
||||
@ -1947,6 +1957,18 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\
|
||||
TEST_PASS("ChaCha20-Poly1305 AEAD test passed!\n");
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ASCON
|
||||
if ( (ret = ascon_hash256_test()) != 0)
|
||||
return err_sys("ASCON Hash test failed!\n", ret);
|
||||
else
|
||||
TEST_PASS("ASCON Hash test passed!\n");
|
||||
|
||||
if ( (ret = ascon_aead128_test()) != 0)
|
||||
return err_sys("ASCON AEAD test failed!\n", ret);
|
||||
else
|
||||
TEST_PASS("ASCON AEAD test passed!\n");
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_XCHACHA) && defined(HAVE_POLY1305)
|
||||
if ( (ret = XChaCha20Poly1305_test()) != 0)
|
||||
TEST_FAIL("XChaCha20-Poly1305 AEAD test failed!\n", ret);
|
||||
@ -8784,6 +8806,254 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t chacha20_poly1305_aead_test(void)
|
||||
}
|
||||
#endif /* HAVE_CHACHA && HAVE_POLY1305 */
|
||||
|
||||
#ifdef HAVE_ASCON
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ascon_hash256_test(void)
|
||||
{
|
||||
WOLFSSL_SMALL_STACK_STATIC byte msg[1024];
|
||||
byte mdOut[ASCON_HASH256_SZ];
|
||||
|
||||
/* KATs taken from https://github.com/ascon/ascon-c.
|
||||
* Testing only a subset of KATs here. The rest are tested in
|
||||
* tests/api/ascon.c. */
|
||||
/* crypto_hash/asconhash256/LWC_HASH_KAT_256.txt
|
||||
* The message is just the byte stream 00 01 02 03 ... */
|
||||
WOLFSSL_SMALL_STACK_STATIC const byte hash_output[][32] = {
|
||||
{ 0x0B, 0x3B, 0xE5, 0x85, 0x0F, 0x2F, 0x6B, 0x98, 0xCA, 0xF2, 0x9F, 0x8F, 0xDE, 0xA8, 0x9B, 0x64, 0xA1, 0xFA, 0x70, 0xAA, 0x24, 0x9B, 0x8F, 0x83, 0x9B, 0xD5, 0x3B, 0xAA, 0x30, 0x4D, 0x92, 0xB2 },
|
||||
{ 0x07, 0x28, 0x62, 0x10, 0x35, 0xAF, 0x3E, 0xD2, 0xBC, 0xA0, 0x3B, 0xF6, 0xFD, 0xE9, 0x00, 0xF9, 0x45, 0x6F, 0x53, 0x30, 0xE4, 0xB5, 0xEE, 0x23, 0xE7, 0xF6, 0xA1, 0xE7, 0x02, 0x91, 0xBC, 0x80 },
|
||||
{ 0x61, 0x15, 0xE7, 0xC9, 0xC4, 0x08, 0x1C, 0x27, 0x97, 0xFC, 0x8F, 0xE1, 0xBC, 0x57, 0xA8, 0x36, 0xAF, 0xA1, 0xC5, 0x38, 0x1E, 0x55, 0x6D, 0xD5, 0x83, 0x86, 0x0C, 0xA2, 0xDF, 0xB4, 0x8D, 0xD2 },
|
||||
{ 0x26, 0x5A, 0xB8, 0x9A, 0x60, 0x9F, 0x5A, 0x05, 0xDC, 0xA5, 0x7E, 0x83, 0xFB, 0xBA, 0x70, 0x0F, 0x9A, 0x2D, 0x2C, 0x42, 0x11, 0xBA, 0x4C, 0xC9, 0xF0, 0xA1, 0xA3, 0x69, 0xE1, 0x7B, 0x91, 0x5C },
|
||||
{ 0xD7, 0xE4, 0xC7, 0xED, 0x9B, 0x8A, 0x32, 0x5C, 0xD0, 0x8B, 0x9E, 0xF2, 0x59, 0xF8, 0x87, 0x70, 0x54, 0xEC, 0xD8, 0x30, 0x4F, 0xE1, 0xB2, 0xD7, 0xFD, 0x84, 0x71, 0x37, 0xDF, 0x67, 0x27, 0xEE },
|
||||
};
|
||||
|
||||
wc_AsconHash256 asconHash;
|
||||
int err;
|
||||
word32 i;
|
||||
|
||||
/* init msg buffer */
|
||||
for (i = 0; i < sizeof(msg); i++)
|
||||
msg[i] = (byte)i;
|
||||
|
||||
for (i = 0; i < XELEM_CNT(hash_output); i++) {
|
||||
XMEMSET(mdOut, 0, sizeof(mdOut));
|
||||
err = wc_AsconHash256_Init(&asconHash);
|
||||
if (err != 0)
|
||||
return WC_TEST_RET_ENC_EC(err);
|
||||
err = wc_AsconHash256_Update(&asconHash, msg, i);
|
||||
if (err != 0)
|
||||
return WC_TEST_RET_ENC_EC(err);
|
||||
err = wc_AsconHash256_Final(&asconHash, mdOut);
|
||||
if (err != 0)
|
||||
return WC_TEST_RET_ENC_EC(err);
|
||||
if (XMEMCMP(mdOut, hash_output[i], ASCON_HASH256_SZ) != 0)
|
||||
return WC_TEST_RET_ENC_NC;
|
||||
wc_AsconHash256_Clear(&asconHash);
|
||||
}
|
||||
|
||||
/* Test separated update */
|
||||
for (i = 0; i < XELEM_CNT(hash_output); i++) {
|
||||
word32 half_i = i / 2;
|
||||
XMEMSET(mdOut, 0, sizeof(mdOut));
|
||||
err = wc_AsconHash256_Init(&asconHash);
|
||||
if (err != 0)
|
||||
return WC_TEST_RET_ENC_EC(err);
|
||||
err = wc_AsconHash256_Update(&asconHash, msg, half_i);
|
||||
if (err != 0)
|
||||
return WC_TEST_RET_ENC_EC(err);
|
||||
err = wc_AsconHash256_Update(&asconHash, msg + half_i, i - half_i);
|
||||
if (err != 0)
|
||||
return WC_TEST_RET_ENC_EC(err);
|
||||
err = wc_AsconHash256_Final(&asconHash, mdOut);
|
||||
if (err != 0)
|
||||
return WC_TEST_RET_ENC_EC(err);
|
||||
if (XMEMCMP(mdOut, hash_output[i], ASCON_HASH256_SZ) != 0)
|
||||
return WC_TEST_RET_ENC_NC;
|
||||
wc_AsconHash256_Clear(&asconHash);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ascon_aead128_test(void)
|
||||
{
|
||||
word32 i;
|
||||
wc_AsconAEAD128 asconAEAD;
|
||||
int err;
|
||||
|
||||
/* KATs taken from https://github.com/ascon/ascon-c.
|
||||
* Testing only a subset of KATs here. The rest are tested in
|
||||
* tests/api/ascon.c. */
|
||||
/* crypto_hash/asconaead128/LWC_AEAD_KAT_128_128.txt */
|
||||
static const char *aead_kat[][5] = {
|
||||
{ /* Key = */ "000102030405060708090A0B0C0D0E0F",
|
||||
/* Nonce = */ "000102030405060708090A0B0C0D0E0F",
|
||||
/* PT = */ "",
|
||||
/* AD = */ "",
|
||||
/* CT = */ "4427D64B8E1E1451FC445960F0839BB0", },
|
||||
{ /* Key = */ "000102030405060708090A0B0C0D0E0F",
|
||||
/* Nonce = */ "000102030405060708090A0B0C0D0E0F",
|
||||
/* PT = */ "",
|
||||
/* AD = */ "00",
|
||||
/* CT = */ "103AB79D913A0321287715A979BB8585", },
|
||||
{ /* Key = */ "000102030405060708090A0B0C0D0E0F",
|
||||
/* Nonce = */ "000102030405060708090A0B0C0D0E0F",
|
||||
/* PT = */ "",
|
||||
/* AD = */ "0001",
|
||||
/* CT = */ "A50E88E30F923B90A9C810181230DF10", },
|
||||
{ /* Key = */ "000102030405060708090A0B0C0D0E0F",
|
||||
/* Nonce = */ "000102030405060708090A0B0C0D0E0F",
|
||||
/* PT = */ "",
|
||||
/* AD = */ "000102",
|
||||
/* CT = */ "AE214C9F66630658ED8DC7D31131174C", },
|
||||
{ /* Key = */ "000102030405060708090A0B0C0D0E0F",
|
||||
/* Nonce = */ "000102030405060708090A0B0C0D0E0F",
|
||||
/* PT = */ "",
|
||||
/* AD = */ "00010203",
|
||||
/* CT = */ "C6FF3CF70575B144B955820D9BC7685E", },
|
||||
};
|
||||
|
||||
for (i = 0; i < XELEM_CNT(aead_kat); i++) {
|
||||
byte key[ASCON_AEAD128_KEY_SZ];
|
||||
byte nonce[ASCON_AEAD128_NONCE_SZ];
|
||||
byte pt[32]; /* longest plaintext we test is 32 bytes */
|
||||
word32 ptSz;
|
||||
byte ad[32]; /* longest AD we test is 32 bytes */
|
||||
word32 adSz;
|
||||
byte ct[48]; /* longest ciphertext we test is 32 bytes + 16 bytes tag */
|
||||
word32 ctSz;
|
||||
word32 j;
|
||||
byte tag[ASCON_AEAD128_TAG_SZ];
|
||||
byte buf[32]; /* longest buffer we test is 32 bytes */
|
||||
|
||||
XMEMSET(key, 0, sizeof(key));
|
||||
XMEMSET(nonce, 0, sizeof(nonce));
|
||||
XMEMSET(pt, 0, sizeof(pt));
|
||||
XMEMSET(ad, 0, sizeof(ad));
|
||||
XMEMSET(ct, 0, sizeof(ct));
|
||||
XMEMSET(tag, 0, sizeof(tag));
|
||||
|
||||
/* Convert HEX strings to byte stream */
|
||||
for (j = 0; aead_kat[i][0][j] != '\0'; j += 2) {
|
||||
key[j/2] = HexCharToByte(aead_kat[i][0][j]) << 4 |
|
||||
HexCharToByte(aead_kat[i][0][j+1]);
|
||||
}
|
||||
for (j = 0; aead_kat[i][1][j] != '\0'; j += 2) {
|
||||
nonce[j/2] = HexCharToByte(aead_kat[i][1][j]) << 4 |
|
||||
HexCharToByte(aead_kat[i][1][j+1]);
|
||||
}
|
||||
for (j = 0; aead_kat[i][2][j] != '\0'; j += 2) {
|
||||
pt[j/2] = HexCharToByte(aead_kat[i][2][j]) << 4 |
|
||||
HexCharToByte(aead_kat[i][2][j+1]);
|
||||
}
|
||||
ptSz = j/2;
|
||||
for (j = 0; aead_kat[i][3][j] != '\0'; j += 2) {
|
||||
ad[j/2] = HexCharToByte(aead_kat[i][3][j]) << 4 |
|
||||
HexCharToByte(aead_kat[i][3][j+1]);
|
||||
}
|
||||
adSz = j/2;
|
||||
for (j = 0; aead_kat[i][4][j] != '\0'; j += 2) {
|
||||
ct[j/2] = HexCharToByte(aead_kat[i][4][j]) << 4 |
|
||||
HexCharToByte(aead_kat[i][4][j+1]);
|
||||
}
|
||||
ctSz = j/2 - ASCON_AEAD128_TAG_SZ;
|
||||
|
||||
for (j = 0; j < 4; j++) {
|
||||
err = wc_AsconAEAD128_Init(&asconAEAD);
|
||||
if (err != 0)
|
||||
return WC_TEST_RET_ENC_EC(err);
|
||||
|
||||
err = wc_AsconAEAD128_SetKey(&asconAEAD, key);
|
||||
if (err != 0)
|
||||
return WC_TEST_RET_ENC_EC(err);
|
||||
|
||||
err = wc_AsconAEAD128_SetNonce(&asconAEAD, nonce);
|
||||
if (err != 0)
|
||||
return WC_TEST_RET_ENC_EC(err);
|
||||
|
||||
err = wc_AsconAEAD128_SetAD(&asconAEAD, ad, adSz);
|
||||
if (err != 0)
|
||||
return WC_TEST_RET_ENC_EC(err);
|
||||
|
||||
if (j == 0) {
|
||||
/* Encryption test */
|
||||
err = wc_AsconAEAD128_EncryptUpdate(&asconAEAD, buf, pt, ptSz);
|
||||
if (err != 0)
|
||||
return WC_TEST_RET_ENC_EC(err);
|
||||
|
||||
if (XMEMCMP(buf, ct, ptSz) != 0)
|
||||
return WC_TEST_RET_ENC_NC;
|
||||
|
||||
err = wc_AsconAEAD128_EncryptFinal(&asconAEAD, tag);
|
||||
if (err != 0)
|
||||
return WC_TEST_RET_ENC_EC(err);
|
||||
|
||||
if (XMEMCMP(tag, ct + ptSz, ASCON_AEAD128_TAG_SZ) != 0)
|
||||
return WC_TEST_RET_ENC_NC;
|
||||
}
|
||||
else if (j == 1) {
|
||||
/* Decryption test */
|
||||
err = wc_AsconAEAD128_DecryptUpdate(&asconAEAD, buf, ct, ctSz);
|
||||
if (err != 0)
|
||||
return WC_TEST_RET_ENC_EC(err);
|
||||
|
||||
if (XMEMCMP(buf, pt, ctSz) != 0)
|
||||
return WC_TEST_RET_ENC_NC;
|
||||
|
||||
err = wc_AsconAEAD128_DecryptFinal(&asconAEAD, ct + ctSz);
|
||||
if (err != 0)
|
||||
return WC_TEST_RET_ENC_EC(err);
|
||||
}
|
||||
else if (j == 2) {
|
||||
/* Split encryption test */
|
||||
err = wc_AsconAEAD128_EncryptUpdate(&asconAEAD, buf, pt,
|
||||
ptSz/2);
|
||||
if (err != 0)
|
||||
return WC_TEST_RET_ENC_EC(err);
|
||||
|
||||
err = wc_AsconAEAD128_EncryptUpdate(&asconAEAD, buf + (ptSz/2),
|
||||
pt + (ptSz/2), ptSz - (ptSz/2));
|
||||
if (err != 0)
|
||||
return WC_TEST_RET_ENC_EC(err);
|
||||
|
||||
if (XMEMCMP(buf, ct, ptSz) != 0)
|
||||
return WC_TEST_RET_ENC_NC;
|
||||
|
||||
err = wc_AsconAEAD128_EncryptFinal(&asconAEAD, tag);
|
||||
if (err != 0)
|
||||
return WC_TEST_RET_ENC_EC(err);
|
||||
|
||||
if (XMEMCMP(tag, ct + ptSz, ASCON_AEAD128_TAG_SZ) != 0)
|
||||
return WC_TEST_RET_ENC_NC;
|
||||
|
||||
}
|
||||
else if (j == 3) {
|
||||
/* Split decryption test */
|
||||
err = wc_AsconAEAD128_DecryptUpdate(&asconAEAD, buf, ct,
|
||||
ctSz/2);
|
||||
if (err != 0)
|
||||
return WC_TEST_RET_ENC_EC(err);
|
||||
|
||||
err = wc_AsconAEAD128_DecryptUpdate(&asconAEAD, buf + (ctSz/2),
|
||||
ct + (ctSz/2), ctSz - (ctSz/2));
|
||||
if (err != 0)
|
||||
return WC_TEST_RET_ENC_EC(err);
|
||||
|
||||
if (XMEMCMP(buf, pt, ctSz) != 0)
|
||||
return WC_TEST_RET_ENC_NC;
|
||||
|
||||
err = wc_AsconAEAD128_DecryptFinal(&asconAEAD, ct + ctSz);
|
||||
if (err != 0)
|
||||
return WC_TEST_RET_ENC_EC(err);
|
||||
|
||||
}
|
||||
|
||||
|
||||
wc_AsconAEAD128_Clear(&asconAEAD);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* HAVE_ASCON */
|
||||
|
||||
#ifndef NO_DES3
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t des_test(void)
|
||||
|
109
wolfssl/wolfcrypt/ascon.h
Normal file
109
wolfssl/wolfcrypt/ascon.h
Normal file
@ -0,0 +1,109 @@
|
||||
/* ascon.h
|
||||
*
|
||||
* Copyright (C) 2006-2025 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfSSL.
|
||||
*
|
||||
* wolfSSL is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfSSL is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
#ifndef WOLF_CRYPT_ASCON_H
|
||||
#define WOLF_CRYPT_ASCON_H
|
||||
|
||||
#ifdef HAVE_ASCON
|
||||
|
||||
#include <wolfssl/wolfcrypt/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ASCON_HASH256_SZ 32
|
||||
|
||||
#define ASCON_AEAD128_KEY_SZ 16
|
||||
#define ASCON_AEAD128_NONCE_SZ 16
|
||||
#define ASCON_AEAD128_TAG_SZ 16
|
||||
|
||||
typedef union AsconState {
|
||||
#ifdef WORD64_AVAILABLE
|
||||
word64 s64[5];
|
||||
#endif
|
||||
word32 s32[10];
|
||||
word16 s16[20];
|
||||
byte s8[40];
|
||||
} AsconState;
|
||||
|
||||
typedef struct wc_AsconHash256 {
|
||||
AsconState state;
|
||||
byte lastBlkSz;
|
||||
} wc_AsconHash256;
|
||||
|
||||
enum {
|
||||
ASCON_AEAD128_NOTSET = 0,
|
||||
ASCON_AEAD128_ENCRYPT = 1,
|
||||
ASCON_AEAD128_DECRYPT = 2
|
||||
};
|
||||
|
||||
typedef struct wc_AsconAEAD128 {
|
||||
/* needed throughout both encrypt and decrypt */
|
||||
#ifdef WORD64_AVAILABLE
|
||||
word64 key[ASCON_AEAD128_KEY_SZ/sizeof(word64)];
|
||||
#endif
|
||||
AsconState state;
|
||||
byte lastBlkSz;
|
||||
byte keySet:1; /* has the key been processed */
|
||||
byte nonceSet:1; /* has the nonce been processed */
|
||||
byte adSet:1; /* has the associated data been processed */
|
||||
byte op:2; /* 0 for not set, 1 for encrypt, 2 for decrypt */
|
||||
} wc_AsconAEAD128;
|
||||
|
||||
/* AsconHash API */
|
||||
|
||||
WOLFSSL_API wc_AsconHash256* wc_AsconHash256_New(void);
|
||||
WOLFSSL_API void wc_AsconHash256_Free(wc_AsconHash256* a);
|
||||
WOLFSSL_API int wc_AsconHash256_Init(wc_AsconHash256* a);
|
||||
WOLFSSL_API void wc_AsconHash256_Clear(wc_AsconHash256* a);
|
||||
WOLFSSL_API int wc_AsconHash256_Update(wc_AsconHash256* a, const byte* data,
|
||||
word32 dataSz);
|
||||
WOLFSSL_API int wc_AsconHash256_Final(wc_AsconHash256* a, byte* hash);
|
||||
|
||||
WOLFSSL_API wc_AsconAEAD128* wc_AsconAEAD128_New(void);
|
||||
WOLFSSL_API void wc_AsconAEAD128_Free(wc_AsconAEAD128* a);
|
||||
WOLFSSL_API int wc_AsconAEAD128_Init(wc_AsconAEAD128* a);
|
||||
WOLFSSL_API void wc_AsconAEAD128_Clear(wc_AsconAEAD128* a);
|
||||
|
||||
/* AsconAEAD API */
|
||||
|
||||
WOLFSSL_API int wc_AsconAEAD128_SetKey(wc_AsconAEAD128* a, const byte* key);
|
||||
WOLFSSL_API int wc_AsconAEAD128_SetNonce(wc_AsconAEAD128* a, const byte* nonce);
|
||||
WOLFSSL_API int wc_AsconAEAD128_SetAD(wc_AsconAEAD128* a, const byte* ad,
|
||||
word32 adSz);
|
||||
|
||||
WOLFSSL_API int wc_AsconAEAD128_EncryptUpdate(wc_AsconAEAD128* a, byte* out,
|
||||
const byte* in, word32 inSz);
|
||||
WOLFSSL_API int wc_AsconAEAD128_EncryptFinal(wc_AsconAEAD128* a, byte* tag);
|
||||
|
||||
WOLFSSL_API int wc_AsconAEAD128_DecryptUpdate(wc_AsconAEAD128* a, byte* out,
|
||||
const byte* in, word32 inSz);
|
||||
WOLFSSL_API int wc_AsconAEAD128_DecryptFinal(wc_AsconAEAD128* a,
|
||||
const byte* tag);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_ASCON */
|
||||
|
||||
#endif /* WOLF_CRYPT_ASCON_H */
|
@ -303,11 +303,12 @@ enum wolfCrypt_ErrorCodes {
|
||||
WC_SPAN2_FIRST_E = -1000,
|
||||
|
||||
DEADLOCK_AVERTED_E = -1000, /* Deadlock averted -- retry the call */
|
||||
ASCON_AUTH_E = -1001, /* ASCON Authentication check failure */
|
||||
|
||||
WC_SPAN2_LAST_E = -1000, /* Update to indicate last used error code */
|
||||
WC_SPAN2_LAST_E = -1001, /* Update to indicate last used error code */
|
||||
WC_SPAN2_MIN_CODE_E = -1999, /* Last usable code in span 2 */
|
||||
|
||||
WC_LAST_E = -1000, /* the last code used either here or in
|
||||
WC_LAST_E = -1001, /* the last code used either here or in
|
||||
* error-ssl.h
|
||||
*/
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
nobase_include_HEADERS+= \
|
||||
wolfssl/wolfcrypt/aes.h \
|
||||
wolfssl/wolfcrypt/arc4.h \
|
||||
wolfssl/wolfcrypt/ascon.h \
|
||||
wolfssl/wolfcrypt/asn.h \
|
||||
wolfssl/wolfcrypt/asn_public.h \
|
||||
wolfssl/wolfcrypt/poly1305.h \
|
||||
|
@ -4103,7 +4103,8 @@ extern void uITRON4_free(void *p) ;
|
||||
#if (defined(HAVE_LIBOQS) || \
|
||||
defined(HAVE_LIBXMSS) || \
|
||||
defined(HAVE_LIBLMS) || \
|
||||
defined(WOLFSSL_DUAL_ALG_CERTS)) && \
|
||||
defined(WOLFSSL_DUAL_ALG_CERTS) || \
|
||||
defined(HAVE_ASCON)) && \
|
||||
!defined(WOLFSSL_EXPERIMENTAL_SETTINGS)
|
||||
#error Experimental settings without WOLFSSL_EXPERIMENTAL_SETTINGS
|
||||
#endif
|
||||
|
@ -1110,6 +1110,7 @@ typedef struct w64wrapper {
|
||||
DYNAMIC_TYPE_BIO = 102,
|
||||
DYNAMIC_TYPE_X509_ACERT = 103,
|
||||
DYNAMIC_TYPE_OS_BUF = 104,
|
||||
DYNAMIC_TYPE_ASCON = 105,
|
||||
DYNAMIC_TYPE_SNIFFER_SERVER = 1000,
|
||||
DYNAMIC_TYPE_SNIFFER_SESSION = 1001,
|
||||
DYNAMIC_TYPE_SNIFFER_PB = 1002,
|
||||
|
Reference in New Issue
Block a user