/**
 * @file
 * Ascon cipher - Lightweight Authenticated Encryption & Hashing,
 * also with Init-Update-Final paradigm.
 *
 * Ascon is a family of authenticated encryption and hashing algorithms
 * designed to be lightweight and easy to implement, even with added
 * countermeasures against side-channel attacks.
 *
 * For more information on the Ascon cipher itself, visit
 * https://ascon.iaik.tugraz.at/
 *
 * This file is the interface to the Ascon library providing:
 * - the Ascon symmetric AEAD ciphers Ascon128, Ascon128a, Ascon80pq
 * - the Ascon fixed-size output hash and variable-size output hash (XOF)
 *
 * All functionalities are available in:
 * - online form (init-update-final paradigm): the data is processed one
 *   chunk at the time; useful if it's still being received or does not
 *   fit into memory
 * - offline form: the data is available as a whole in memory and processed
 *   in one go
 *
 * Library dependencies:
 * - only the C99 or C11 standard library, as seen in the `#include` statements
 *   of this file
 *
 * @license Creative Commons Zero (CC0) 1.0
 * @authors See AUTHORS.md file
 */

#ifndef ASCON_H
#define ASCON_H

#ifdef __cplusplus
extern "C"
{
#endif

#include <stdint.h> /* For uint8_t, uint_fast8_t, uint64_t */
#include <stddef.h> /* For size_t, NULL */
#include <stdbool.h> /* For bool, true, false */

#if defined(ASCON_INPUT_ASSERTS) && !defined(ASCON_ASSERT)
/**
 * @def ASCON_INPUT_ASSERTS
 * When defined, enables the runtime assertions on the parameters of all
 * functions of the library API using #ASCON_ASSERT - undefined (disabled)
 * by default.
 * The check is mostly against NULL pointers, for the correct order of calling
 * of the many Init-Update-Final functions and against mixing functions from
 * different AEAD algorithms (128 vs 128a vs 80pq). It's generally useful
 * for debugging only.
 * @see ASCON_ASSERT
 */
// Redefining ASCON_INPUT_ASSERTS otherwise Doxygen does not find it
#undef ASCON_INPUT_ASSERTS
#define ASCON_INPUT_ASSERTS 1
/**
 * @def ASCON_ASSERT
 * Assertion macro, defaulting to `assert` from `assert.h`, when
 * #ASCON_INPUT_ASSERTS is defined, but #ASCON_ASSERT is not.
 * Redefine it to something else if required.
 */
#include <assert.h> /* For assert() */
#define ASCON_ASSERT(expr) assert(expr)
#endif

/**
 * @def ASCON_API
 * Marker of all the library's public API functions. Used to add exporting
 * indicators for DLL on Windows, empty on other platforms.
 */
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(_WIN64) || defined(__NT__)
/**
 * @def ASCON_WINDOWS
 * Indicator simplifying the check for the Windows platform (undefined on other platforms).
 * Used for internal decisions on how to inline functions.
 */
#define ASCON_WINDOWS 1
#define ASCON_API __declspec(dllexport)
#else
#define ASCON_API
#endif

/** Major version of this API conforming to semantic versioning. */
#define ASCON_API_VERSION_MAJOR 1
/** Minor version of this API conforming to semantic versioning. */
#define ASCON_API_VERSION_MINOR 1
/** Bugfix/patch version of this API conforming to semantic versioning. */
#define ASCON_API_VERSION_BUGFIX 1
/** Version of this API conforming to semantic versioning as a string. */
#define ASCON_API_VERSION "1.1.1"

/**
 * Length in bytes of the secret symmetric key used for the Ascon128 cipher.
 */
#define ASCON_AEAD128_KEY_LEN 16U

/**
 * Length in bytes of the secret symmetric key used for the Ascon128a cipher.
 */
#define ASCON_AEAD128a_KEY_LEN 16U

/**
 * Length in bytes of the secret symmetric key used for the Ascon80pq cipher.
 */
#define ASCON_AEAD80pq_KEY_LEN 20U

/**
 * Length in bytes of the public nonce used for authenticated
 * encryption and decryption.
 */
#define ASCON_AEAD_NONCE_LEN 16U

/**
 * Minimum recommended length in bytes of the authentication tag generated by
 * the authenticated encryption and validated by the decryption.
 */
#define ASCON_AEAD_TAG_MIN_SECURE_LEN 16U

/**
 * Length in bytes of the digest generated by the fixed-size (non-xof) hash
 * function.
 */
#define ASCON_HASH_DIGEST_LEN 32U

/**
 * Number of bytes the cipher can process at the time in AEAD128 mode and
 * hashing.
 */
#define ASCON_RATE 8U

/**
 * Number of bytes the cipher can process at the time in AEAD128a mode.
 *
 * The AEAD128a cipher absorbs blocks twice the standard rate size.
 */
#define ASCON_DOUBLE_RATE (2U * ASCON_RATE)

/**
 * The tag is valid thus the associated data and ciphertext were intact.
 */
#define ASCON_TAG_OK true
/**
 * The tag is invalid thus the associated data and decrypted data should be
 * ignored.
 */
#define ASCON_TAG_INVALID false

/**
 * Internal cipher sponge state (320 bits).
 */
typedef struct
{
    /** Sponge's first field */
    uint64_t x0;
    /** Sponge's second field */
    uint64_t x1;
    /** Sponge's third field */
    uint64_t x2;
    /** Sponge's fourth field */
    uint64_t x3;
    /** Sponge's fifth field */
    uint64_t x4;
} ascon_sponge_t;

/**
 * Internal cipher sponge state associated with a buffer holding for
 * less-than-rate updates. Used for the Init-Update-Final implementation.
 */
typedef struct
{
    /** Cipher sponge state. */
    ascon_sponge_t sponge;

    /** Buffer caching the less-than-rate long input between update calls. */
    uint8_t buffer[ASCON_DOUBLE_RATE];

    /** Currently used bytes of the buffer. */
    uint8_t buffer_len;

    /**
     * State of the order of Init-Update-Final function calls, checked to
     * know when to finalise the associated data processing and for the
     * runtime assertions on the correct order of the functions.
     *
     * @see #ASCON_INPUT_ASSERTS
     *
     * Note: this variable is not semantically relevant in THIS struct,
     * as it should belong in the struct ascon_aead_ctx_t, but by having it
     * here we spare bytes of padding (7 on 64-bit systems, 3 on 32-bit,
     * 1 on 16-bit) at the end of the struct ascon_aead_ctx_t, by using some
     * of the padding space this struct anyway has.
     */
    uint8_t flow_state;

    /** Unused padding to the next uint64_t (sponge.x0 or ctx.k0)
     * to avoid errors when compiling with `-Wpadding` on any platform. */
    uint8_t pad[6];
} ascon_bufstate_t;

/** Cipher context for hashing. */
typedef ascon_bufstate_t ascon_hash_ctx_t;

/**
 * Cipher context for authenticated encryption and validated decryption.
 *
 * Half of this context's size is the cipher's sponge state, the remaining
 * part is holding the key and the buffering of online data (and some padding).
 */
typedef struct
{
    /** Cipher buffered sponge state. */
    ascon_bufstate_t bufstate;

    /** Copy of the secret key, to be used in the final step, first part. */
    uint64_t k0;

    /** Copy of the secret key, to be used in the final step, second part. */
    uint64_t k1;

    /** Copy of the secret key, to be used in the final step, third part,
     * used only in the Ascon80pq cipher. */
    uint64_t k2;
} ascon_aead_ctx_t;

/**
 * Offline symmetric encryption using Ascon128.
 *
 * Encrypts the data which is already available as a whole in a contiguous
 * buffer, authenticating any optional associated data in the process.
 * Provides the ciphertext and the authentication tag as output.
 *
 * In case of no associated data at all to be authenticated, set
 * \p assoc_data_len to 0. Iff that is the case, \p assoc_data can
 * be set to NULL.
 *
 * @image html encrypt.png
 *
 * @warning
 * The nonce **must be unique**, as the strength of the AEAD is based on
 * its uniqueness.
 *
 * @warning
 * Using the AEAD to just authenticate any associated data with no
 * plaintext to be encrypted is not recommended as the AEAD algorithm is not
 * designed for that. Instead use the Ascon hashing or xof functions in the form
 * `Hash(key || msg)`.
 *
 * @param[out] ciphertext encrypted data with the same length as the
 *       plaintext, thus \p plaintext_len will be written in this buffer.
 *       This pointer may also point to the same location as \p plaintext
 *       to encrypt the plaintext in-place, sparing on memory instead
 *       of writing into a separate output buffer. Not NULL.
 * @param[out] tag Message Authentication Code (MAC, a.k.a. cryptographic tag,
 *       fingerprint), used to validate the integrity and authenticity of the
 *       associated data and ciphertext. Has \p tag_len bytes. Not NULL.
 * @param[in] key secret key of #ASCON_AEAD128_KEY_LEN. Not NULL.
 * @param[in] nonce public **unique** nonce of #ASCON_AEAD_NONCE_LEN bytes.
 * @param[in] assoc_data data to be authenticated with the same tag
 *        but not encrypted. Can be NULL iff \p assoc_data_len is 0.
 * @param[in] plaintext data to be encrypted into \p ciphertext.
 * @param[in] assoc_data_len length of the data pointed by \p assoc_data in
 *        bytes. Can be 0.
 * @param[in] plaintext_len length of the data pointed by \p plaintext in
 *        bytes. Can be 0 (not recommended, see warning).
 * @param[in] tag_len length of the tag to generate in bytes. At least
 *       #ASCON_AEAD_TAG_MIN_SECURE_LEN is recommended for security.
 */
ASCON_API void
ascon_aead128_encrypt(uint8_t* ciphertext,
                      uint8_t* tag,
                      const uint8_t key[ASCON_AEAD128_KEY_LEN],
                      const uint8_t nonce[ASCON_AEAD_NONCE_LEN],
                      const uint8_t* assoc_data,
                      const uint8_t* plaintext,
                      size_t assoc_data_len,
                      size_t plaintext_len,
                      size_t tag_len);

/**
 * Online symmetric encryption/decryption using Ascon128, initialisation.
 *
 * Prepares to start a new encryption or decryption session for plaintext or
 * ciphertext and associated data being provided one chunk at the time.
 *
 * The key and nonce are copied/absorbed into the internal state, so they can
 * be deleted from their original location after this function returns.
 *
 * The calling order for encryption/decryption is:
 * 1. ascon_aead128_init() - once only
 * 2. ascon_aead128_assoc_data_update() - 0 or more times
 * 3. ascon_aead128_encrypt_update() / ascon_aead128_decrypt_update() - 0 or
 *    more times, see warning
 * 4. ascon_aead128_encrypt_final() / ascon_aead128_encrypt_final() - once only
 *
 * @image html encrypt.png
 * @image html decrypt.png
 *
 * @warning
 * Using the AEAD to just authenticate any associated data with no
 * plaintext to be encrypted is not recommended as the AEAD algorithm is not
 * designed for that. Instead use the Ascon hashing or xof functions in the form
 * `Hash(key || msg)`.
 *
 * @warning
 * A copy of the secret key is kept in the \p ctx struct and securely erased
 * during the ascon_aead128_encrypt_final() or ascon_aead128_decrypt_final()
 * call. In case the encryption or decryption session is interrupted and never
 * finalised, clear the context with ascon_aead_cleanup() to erase the key copy.
 *
 * @warning
 * Do not mix Init-Update-Final functions across ciphers.
 *
 * @param[in, out] ctx the encryption/decryption context, handling the cipher
 *       state and buffering of incoming data to be processed. Not NULL.
 * @param[in] key secret key of #ASCON_AEAD128_KEY_LEN bytes. Not NULL
 * @param[in] nonce public unique nonce of #ASCON_AEAD_NONCE_LEN bytes. Not
 *       NULL.
 */
ASCON_API void
ascon_aead128_init(ascon_aead_ctx_t* ctx,
                   const uint8_t key[ASCON_AEAD128_KEY_LEN],
                   const uint8_t nonce[ASCON_AEAD_NONCE_LEN]);

/**
 * Online symmetric encryption/decryption using Ascon128, feeding associated
 * data.
 *
 * Feeds a chunk of associated data to the already initialised encryption
 * or decryption session. The data will be authenticated by the tag provided by
 * the final function, but not encrypted or decrypted.
 *
 * In case of no associated data at all to be authenticated/validated, this
 * function can either be either skipped completely or called (also many times)
 * with \p assoc_data_len set to 0. Iff that is the case, \p assoc_data can
 * be set to NULL.
 *
 * After calling ascon_aead128_encrypt_update() or
 * ascon_aead128_decrypt_update(), this function **must** not be used anymore
 * on the same context.
 *
 * The calling order for encryption/decryption is:
 * 1. ascon_aead128_init() - once only
 * 2. ascon_aead128_assoc_data_update() - 0 or more times
 * 3. ascon_aead128_encrypt_update() / ascon_aead128_decrypt_update() - 0 or
 *    more times, see warning
 * 4. ascon_aead128_encrypt_final() / ascon_aead128_encrypt_final() - once only
 *
 * @warning
 * Using the AEAD to just authenticate any associated data with no
 * plaintext to be encrypted is not recommended as the AEAD algorithm is not
 * designed for that. Instead use the Ascon hashing or xof functions in the form
 * `Hash(key || msg)`.
 *
 * @param[in, out] ctx the encryption/decryption context, handling the cipher
 *       state and buffering of incoming data to be processed. Not NULL.
 * @param[in] assoc_data data to be authenticated/validated with the same tag
 *        but not encrypted/decrypted. May be NULL iff \p assoc_data_len is 0.
 * @param[in] assoc_data_len length of the data pointed by \p assoc_data in
 *        bytes. May be 0.
 */
ASCON_API void
ascon_aead128_assoc_data_update(ascon_aead_ctx_t* ctx,
                                const uint8_t* assoc_data,
                                size_t assoc_data_len);

/**
 * Online symmetric encryption using Ascon128, feeding plaintext and getting
 * ciphertext.
 *
 * Feeds a chunk of plaintext data to the encryption session after any
 * optional associated data has been processed. The plaintext will be encrypted
 * and provided as ciphertext in buffered chunks of #ASCON_RATE bytes.
 *
 * It will automatically finalise the absorption of any associated data,
 * so no new associated data could be processed after this function is called.
 *
 * The calling order for encryption is:
 * 1. ascon_aead128_init() - once only
 * 2. ascon_aead128_assoc_data_update() - 0 or more times
 * 3. ascon_aead128_encrypt_update() - 0 or more times, see warning
 * 4. ascon_aead128_encrypt_final() - once only
 *
 * @warning
 * Using the AEAD to just authenticate any associated data with no
 * plaintext to be encrypted is not recommended as the AEAD algorithm is not
 * designed for that. Instead use the Ascon hashing or xof functions in the form
 * `Hash(key || msg)`.
 *
 * @param[in, out] ctx the encryption context, handling the cipher
 *       state and buffering of incoming data to be processed. Not NULL.
 * @param[out] ciphertext encrypted data, buffered into chunks.
 *       This function will write a multiple of #ASCON_RATE bytes in the
 *       interval [0, \p plaintext_len + #ASCON_RATE[ into \p ciphertext.
 *       The exact number of written bytes is indicated by the return value.
 *       This pointer may also point to the same location as \p plaintext
 *       to encrypt the plaintext in-place, sparing on memory instead
 *       of writing into a separate output buffer. Not NULL.
 * @param[in] plaintext data to be encrypted into \p ciphertext. All of the
 *       plaintext will be processed, even if the function provides less than
 *       \p plaintext_len output bytes. They are just buffered. Not NULL.
 * @param[in] plaintext_len length of the data pointed by \p plaintext in
 *        bytes. May be 0.
 * @returns number of bytes written into \p ciphertext. The value is a multiple
 *        of #ASCON_RATE in [0, \p plaintext_len + #ASCON_RATE[.
 */
ASCON_API size_t
ascon_aead128_encrypt_update(ascon_aead_ctx_t* ctx,
                             uint8_t* ciphertext,
                             const uint8_t* plaintext,
                             size_t plaintext_len);

/**
 * Online symmetric encryption using Ascon128, finalisation and tag generation.
 *
 * Finalises the authenticated encryption by returning any remaining buffered
 * ciphertext and the authentication tag. The total ciphertext length is
 * equal to the total plaintext length.
 *
 * It will securely erase the content of the \p ctx struct before returning.
 *
 * The calling order for encryption is:
 * 1. ascon_aead128_init() - once only
 * 2. ascon_aead128_assoc_data_update() - 0 or more times
 * 3. ascon_aead128_encrypt_update() - 0 or more times, see warning
 * 4. ascon_aead128_encrypt_final() - once only
 *
 * @warning
 * Using the AEAD to just authenticate any associated data with no
 * plaintext to be encrypted is not recommended as the AEAD algorithm is not
 * designed for that. Instead use the Ascon hashing or xof functions in the form
 * `Hash(key || msg)`.
 *
 * @warning
 * A copy of the secret key is kept in the \p ctx struct and securely erased
 * during the this function call. In case the encryption session is interrupted
 * and never finalised (this function is never called), clear the context with
 * ascon_aead_cleanup() to erase the key copy.
 *
 * @param[in, out] ctx the encryption context, handling the cipher
 *       state and buffering of incoming data to be processed. It will be erased
 *       securely before this function returns. Not NULL.
 * @param[out] ciphertext trailing encrypted data still available in the
 *       buffer of the buffered updating. This function will write
 *       [0, #ASCON_RATE[ bytes into \p ciphertext.
 *       The exact number of written bytes is indicated by the return value.
 *       Not NULL.
 * @param[out] tag Message Authentication Code (MAC, a.k.a. cryptographic tag,
 *       fingerprint), used to validate the integrity and authenticity of the
 *       associated data and ciphertext. Has \p tag_len bytes. Not NULL.
 * @param[in] tag_len length of the tag to generate in bytes. At least
 *       #ASCON_AEAD_TAG_MIN_SECURE_LEN is recommended for security.
 * @returns number of bytes written into \p ciphertext. The value is in the
 *        interval [0, #ASCON_RATE[, i.e. whatever remained in the buffer
 *        after the last update call.
 */
ASCON_API size_t
ascon_aead128_encrypt_final(ascon_aead_ctx_t* ctx,
                            uint8_t* ciphertext,
                            uint8_t* tag,
                            size_t tag_len);

/**
 * Offline symmetric decryption using Ascon128.
 *
 * Decrypts the data which is already available as a whole in a contiguous
 * buffer, validating any optional associated data in the process.
 * Provides the plaintext and the validity of the authentication tag as output.
 * The total plaintext length is equal to the total ciphertext length.
 *
 * In case of no associated data at all to be authenticated, set
 * \p assoc_data_len to 0. Iff that is the case, \p assoc_data can
 * be set to NULL.
 *
 * @image html decrypt.png
 *
 * @param[out] plaintext decrypted data with the same length as the
 *       ciphertext, thus \p ciphertext_len will be written in this buffer.
 *       This pointer may also point to the same location as \p ciphertext
 *       to decrypt the ciphertext in-place, sparing on memory instead
 *       of writing into a separate output buffer. Not NULL.
 * @param[in] key secret key of #ASCON_AEAD128_KEY_LEN bytes. Not NULL.
 * @param[in] nonce public unique nonce of #ASCON_AEAD_NONCE_LEN bytes.
 * @param[in] assoc_data data to be validated with the same tag
 *        but not decrypted. Can be NULL iff \p assoc_data_len is 0.
 * @param[in] ciphertext data to be decrypted into \p plaintext.
 * @param[in] expected_tag Message Authentication Code (MAC, a.k.a. cryptographic tag,
 *       fingerprint), used to validate the integrity and authenticity of the
 *       associated data and ciphertext. Has \p tag_len bytes. Not NULL.
 * @param[in] assoc_data_len length of the data pointed by \p assoc_data in
 *        bytes. Can be 0.
 * @param[in] ciphertext_len length of the data pointed by \p ciphertext in
 *        bytes. Can be 0 (not recommended, see warning of
 *        ascon_aead128_encrypt()).
 * @param[in] expected_tag_len length of the \p tag to check in bytes. It should be
 *       the same length as generated during the encryption
 *       but it can be shorter (although it's not recommended).
 * @returns the answer to the question "is tha tag valid?", thus
 *        `true` (== #ASCON_TAG_OK) if the validation of the tag is correct,
 *        thus the associated data and ciphertext are intact and authentic.
 *        `false` (== #ASCON_TAG_INVALID) otherwise.
 */
ASCON_API bool
ascon_aead128_decrypt(uint8_t* plaintext,
                      const uint8_t key[ASCON_AEAD128_KEY_LEN],
                      const uint8_t nonce[ASCON_AEAD_NONCE_LEN],
                      const uint8_t* assoc_data,
                      const uint8_t* ciphertext,
                      const uint8_t* expected_tag,
                      size_t assoc_data_len,
                      size_t ciphertext_len,
                      size_t expected_tag_len);

/**
 * Online symmetric decryption using Ascon128, feeding ciphertext and getting
 * plaintext.
 *
 * Feeds a chunk of ciphertext data to the decryption session after any
 * optional associated data has been processed. The ciphertext will be decrypted
 * and provided back in buffered chunks of #ASCON_RATE bytes.
 *
 * It will automatically finalise the absorption of any associated data,
 * so no new associated data could be processed after this function is called.
 *
 * The calling order for decryption is:
 * 1. ascon_aead128_init() - once only
 * 2. ascon_aead128_assoc_data_update() - 0 or more times
 * 3. ascon_aead128_decrypt_update() - 0 or more times, see warning
 * 4. ascon_aead128_decrypt_final() - once only
 *
 * @param[in, out] ctx the decryption context, handling the cipher state
 *       and buffering of incoming data to be processed. Not NULL.
 * @param[out] plaintext decrypted data, buffered into chunks.
 *       This function will write a multiple of #ASCON_RATE bytes in the
 *       interval [0, \p ciphertext_len + #ASCON_RATE[ into \p plaintext.
 *       The exact number of written bytes is indicated by the return value.
 *       This pointer may also point to the same location as \p ciphertext
 *       to decrypt the ciphertext in-place, sparing on memory instead
 *       of writing into a separate output buffer. Not NULL.
 * @param[in] ciphertext data to be decrypted into \p plaintext. All of the
 *       ciphertext will be processed, even if the function provides less than
 *       \p ciphertext_len output bytes. They are just buffered. Not NULL.
 * @param[in] ciphertext_len length of the data pointed by \p ciphertext in
 *        bytes. May be 0.
 * @returns number of bytes written into \p plaintext. The value is a multiple
 *        of #ASCON_RATE in [0, \p ciphertext_len + #ASCON_RATE[.
 */
ASCON_API size_t
ascon_aead128_decrypt_update(ascon_aead_ctx_t* ctx,
                             uint8_t* plaintext,
                             const uint8_t* ciphertext,
                             size_t ciphertext_len);

/**
 * Online symmetric decryption using Ascon128, finalisation and tag validation.
 *
 * Finalises the authenticated decryption by returning any remaining buffered
 * plaintext and the validity of the authentication tag.
 * The total plaintext length is equal to the total ciphertext length.
 *
 * It will securely erase the content of the \p ctx struct before returning.
 *
 * The calling order for decryption is:
 * 1. ascon_aead128_init() - once only
 * 2. ascon_aead128_assoc_data_update() - 0 or more times
 * 3. ascon_aead128_decrypt_update() - 0 or more times, see warning
 * 4. ascon_aead128_decrypt_final() - once only
 *
 * @warning
 * A copy of the secret key is kept in the \p ctx struct and securely erased
 * during the this function call. In case the decryption session is interrupted
 * and never finalised (this function is never called), clear the context with
 * ascon_aead_cleanup() to erase the key copy.
 *
 * @param[in, out] ctx the decryption context, handling the cipher
 *       state and buffering of incoming data to be processed. It will be erased
 *       securely before this function returns. Not NULL.
 * @param[out] plaintext trailing decrypted data still available in the
 *       buffer of the buffered updating. This function will write
 *       [0, #ASCON_RATE[ bytes into \p plaintext.
 *       The exact number of written bytes is indicated by the return value.
 *       Not NULL.
 * @param[out] is_tag_valid the answer to the question "is the tag valid?", thus
 *        `true` (== #ASCON_TAG_OK) if the validation of the tag is correct,
 *        thus the associated data and ciphertext are intact and authentic.
 *        `false` (== #ASCON_TAG_INVALID) otherwise.
 * @param[in] expected_tag Message Authentication Code (MAC, a.k.a. cryptographic tag,
 *       fingerprint), used to validate the integrity and authenticity of the
 *       associated data and ciphertext. Has \p tag_len bytes. Not NULL.
 * @param[in] expected_tag_len length of the \p tag to check in bytes. It should be
 *       the same length as generated during the encryption
 *       but it can be shorter (although it's not recommended).
 * @returns number of bytes written into \p plaintext. The value is in the
 *        interval [0, #ASCON_RATE[, i.e. whatever remained in the buffer
 *        after the last update call.
 */
ASCON_API size_t
ascon_aead128_decrypt_final(ascon_aead_ctx_t* ctx,
                            uint8_t* plaintext,
                            bool* is_tag_valid,
                            const uint8_t* expected_tag,
                            size_t expected_tag_len);

/**
 * Security cleanup of the AEAD context, in case the online processing
 * is not completed to the end.
 *
 * Use this function only when something goes wrong between the calls of
 * online encryption or decryption and you never call the
 * `ascon_aead*_encrypt_final()` or `ascon_aead*_decrypt_final()` functions
 * of the cipher you are currently using (because these 2 functions perform the
 * cleanup automatically).
 *
 * This is to prevent any information (especially the key!) to leak through the
 * context in case an encryption/decryption transaction is rolled back/abruptly
 * terminated.
 *
 * @param[in, out] ctx to erase.
 */
ASCON_API void
ascon_aead_cleanup(ascon_aead_ctx_t* ctx);

/**
 * Offline symmetric encryption using Ascon128a, which uses a double data rate
 * compared to Ascon128.
 *
 * Encrypts the data which is already available as a whole in a contiguous
 * buffer, authenticating any optional associated data in the process.
 * Provides the ciphertext and the authentication tag as output.
 *
 * In case of no associated data at all to be authenticated, set
 * \p assoc_data_len to 0. Iff that is the case, \p assoc_data can
 * be set to NULL.
 *
 * @image html encrypt.png
 *
 * @warning
 * The nonce **must be unique**, as the strength of the AEAD is based on
 * its uniqueness.
 *
 * @warning
 * Using the AEAD to just authenticate any associated data with no
 * plaintext to be encrypted is not recommended as the AEAD algorithm is not
 * designed for that. Instead use the Ascon hashing or xof functions in the form
 * `Hash(key || msg)`.
 *
 * @param[out] ciphertext encrypted data with the same length as the
 *       plaintext, thus \p plaintext_len will be written in this buffer.
 *       This pointer may also point to the same location as \p plaintext
 *       to encrypt the plaintext in-place, sparing on memory instead
 *       of writing into a separate output buffer. Not NULL.
 * @param[out] tag Message Authentication Code (MAC, a.k.a. cryptographic tag,
 *       fingerprint), used to validate the integrity and authenticity of the
 *       associated data and ciphertext. Has \p tag_len bytes. Not NULL.
 * @param[in] key secret key of #ASCON_AEAD128a_KEY_LEN bytes. Not NULL.
 * @param[in] nonce public **unique** nonce of #ASCON_AEAD_NONCE_LEN bytes.
 * @param[in] assoc_data data to be authenticated with the same tag
 *        but not encrypted. Can be NULL iff \p assoc_data_len is 0.
 * @param[in] plaintext data to be encrypted into \p ciphertext.
 * @param[in] assoc_data_len length of the data pointed by \p assoc_data in
 *        bytes. Can be 0.
 * @param[in] plaintext_len length of the data pointed by \p plaintext in
 *        bytes. Can be 0 (not recommended, see warning).
 * @param[in] tag_len length of the tag to generate in bytes. At least
 *       #ASCON_AEAD_TAG_MIN_SECURE_LEN is recommended for security.
*/
ASCON_API void
ascon_aead128a_encrypt(uint8_t* ciphertext,
                       uint8_t* tag,
                       const uint8_t key[ASCON_AEAD128_KEY_LEN],
                       const uint8_t nonce[ASCON_AEAD_NONCE_LEN],
                       const uint8_t* assoc_data,
                       const uint8_t* plaintext,
                       size_t assoc_data_len,
                       size_t plaintext_len,
                       size_t tag_len);


/**
 * Online symmetric encryption/decryption using Ascon128a, initialisation.
 *
 * Prepares to start a new encryption or decryption session for plaintext or
 * ciphertext and associated data being provided one chunk at the time.
 *
 * The key and nonce are copied/absorbed into the internal state, so they can
 * be deleted from their original location after this function returns.
 *
 * The calling order for encryption/decryption is:
 * 1. ascon_aead128a_init() - once only
 * 2. ascon_aead128a_assoc_data_update() - 0 or more times
 * 3. ascon_aead128a_encrypt_update() / ascon_aead128a_decrypt_update() - 0 or
 *    more times, see warning
 * 4. ascon_aead128a_encrypt_final() / ascon_aead128a_encrypt_final() - once
 * only
 *
 * @image html encrypt.png
 * @image html decrypt.png
 *
 * @warning
 * Using the AEAD to just authenticate any associated data with no
 * plaintext to be encrypted is not recommended as the AEAD algorithm is not
 * designed for that. Instead use the Ascon hashing or xof functions in the form
 * `Hash(key || msg)`.
 *
 * @warning
 * A copy of the secret key is kept in the \p ctx struct and securely erased
 * during the ascon_aead128a_encrypt_final() or ascon_aead128a_decrypt_final()
 * call. In case the encryption or decryption session is interrupted and never
 * finalised, clear the context with ascon_aead_cleanup() to erase the key copy.
 *
 * @warning
 * Do not mix Init-Update-Final functions across ciphers.
 *
 * @param[in, out] ctx the encryption/decryption context, handling the cipher
 *       state and buffering of incoming data to be processed. Not NULL.
 * @param[in] key secret key of #ASCON_AEAD128a_KEY_LEN bytes. Not NULL
 * @param[in] nonce public unique nonce of #ASCON_AEAD_NONCE_LEN bytes. Not
 *       NULL.
 */
ASCON_API void
ascon_aead128a_init(ascon_aead_ctx_t* ctx,
                    const uint8_t key[ASCON_AEAD128a_KEY_LEN],
                    const uint8_t nonce[ASCON_AEAD_NONCE_LEN]);

/**
 * Online symmetric encryption/decryption using Ascon128a, feeding associated
 * data.
 *
 * Feeds a chunk of associated data to the already initialised encryption
 * or decryption session. The data will be authenticated by the tag provided by
 * the final function, but not encrypted or decrypted.
 *
 * In case of no associated data at all to be authenticated/validated, this
 * function can either be either skipped completely or called (also many times)
 * with \p assoc_data_len set to 0. Iff that is the case, \p assoc_data can
 * be set to NULL.
 *
 * After calling ascon_aead128a_encrypt_update() or
 * ascon_aead128a_decrypt_update(), this function **must** not be used anymore
 * on the same context.
 *
 * The calling order for encryption/decryption is:
 * 1. ascon_aead128a_init() - once only
 * 2. ascon_aead128a_assoc_data_update() - 0 or more times
 * 3. ascon_aead128a_encrypt_update() / ascon_aead128a_decrypt_update() - 0 or
 *    more times, see warning
 * 4. ascon_aead128a_encrypt_final() / ascon_aead128a_encrypt_final() - once
 *    only
 *
 * @warning
 * Using the AEAD to just authenticate any associated data with no
 * plaintext to be encrypted is not recommended as the AEAD algorithm is not
 * designed for that. Instead use the Ascon hashing or xof functions in the form
 * `Hash(key || msg)`.
 *
 * @param[in, out] ctx the encryption/decryption context, handling the cipher
 *       state and buffering of incoming data to be processed. Not NULL.
 * @param[in] assoc_data data to be authenticated/validated with the same tag
 *        but not encrypted/decrypted. May be NULL iff \p assoc_data_len is 0.
 * @param[in] assoc_data_len length of the data pointed by \p assoc_data in
 *        bytes. May be 0.
 */
ASCON_API void
ascon_aead128a_assoc_data_update(ascon_aead_ctx_t* ctx,
                                 const uint8_t* assoc_data,
                                 size_t assoc_data_len);

/**
 * Online symmetric encryption using Ascon128a, feeding plaintext and getting
 * ciphertext.
 *
 * Feeds a chunk of plaintext data to the encryption session after any
 * optional associated data has been processed. The plaintext will be encrypted
 * and provided as ciphertext in buffered chunks of #ASCON_DOUBLE_RATE bytes.
 *
 * It will automatically finalise the absorption of any associated data,
 * so no new associated data could be processed after this function is called.
 *
 * The calling order for encryption is:
 * 1. ascon_aead128a_init() - once only
 * 2. ascon_aead128a_assoc_data_update() - 0 or more times
 * 3. ascon_aead128a_encrypt_update() - 0 or more times, see warning
 * 4. ascon_aead128a_encrypt_final() - once only
 *
 * @warning
 * Using the AEAD to just authenticate any associated data with no
 * plaintext to be encrypted is not recommended as the AEAD algorithm is not
 * designed for that. Instead use the Ascon hashing or xof functions in the form
 * `Hash(key || msg)`.
 *
 * @param[in, out] ctx the encryption context, handling the cipher
 *       state and buffering of incoming data to be processed. Not NULL.
 * @param[out] ciphertext encrypted data, buffered into chunks.
 *       This function will write a multiple of #ASCON_DOUBLE_RATE bytes in the
 *       interval [0, \p plaintext_len + #ASCON_DOUBLE_RATE[ into \p ciphertext.
 *       The exact number of written bytes is indicated by the return value.
 *       This pointer may also point to the same location as \p plaintext
 *       to encrypt the plaintext in-place, sparing on memory instead
 *       of writing into a separate output buffer. Not NULL.
 * @param[in] plaintext data to be encrypted into \p ciphertext. All of the
 *       plaintext will be processed, even if the function provides less than
 *       \p plaintext_len output bytes. They are just buffered. Not NULL.
 * @param[in] plaintext_len length of the data pointed by \p plaintext in
 *        bytes. May be 0.
 * @returns number of bytes written into \p ciphertext. The value is a multiple
 *        of #ASCON_RATE in [0, \p plaintext_len + #ASCON_DOUBLE_RATE[.
 */
ASCON_API size_t
ascon_aead128a_encrypt_update(ascon_aead_ctx_t* ctx,
                              uint8_t* ciphertext,
                              const uint8_t* plaintext,
                              size_t plaintext_len);


/**
 * Online symmetric encryption using Ascon128a, finalisation and tag generation.
 *
 * Finalises the authenticated encryption by returning any remaining buffered
 * ciphertext and the authentication tag. The total ciphertext length is
 * equal to the total plaintext length.
 *
 * It will securely erase the content of the \p ctx struct before returning.
 *
 * The calling order for encryption is:
 * 1. ascon_aead128a_init() - once only
 * 2. ascon_aead128a_assoc_data_update() - 0 or more times
 * 3. ascon_aead128a_encrypt_update() - 0 or more times, see warning
 * 4. ascon_aead128a_encrypt_final() - once only
 *
 * @warning
 * Using the AEAD to just authenticate any associated data with no
 * plaintext to be encrypted is not recommended as the AEAD algorithm is not
 * designed for that. Instead use the Ascon hashing or xof functions in the form
 * `Hash(key || msg)`.
 *
 * @warning
 * A copy of the secret key is kept in the \p ctx struct and securely erased
 * during the this function call. In case the encryption session is interrupted
 * and never finalised (this function is never called), clear the context with
 * ascon_aead_cleanup() to erase the key copy.
 *
 * @param[in, out] ctx the encryption context, handling the cipher
 *       state and buffering of incoming data to be processed. It will be erased
 *       securely before this function returns. Not NULL.
 * @param[out] ciphertext trailing encrypted data still available in the
 *       buffer of the buffered updating. This function will write
 *       [0, #ASCON_DOUBLE_RATE[ bytes into \p ciphertext.
 *       The exact number of written bytes is indicated by the return value.
 *       Not NULL.
 * @param[out] tag Message Authentication Code (MAC, a.k.a. cryptographic tag,
 *       fingerprint), used to validate the integrity and authenticity of the
 *       associated data and ciphertext. Has \p tag_len bytes. Not NULL.
 * @param[in] tag_len length of the tag to generate in bytes. At least
 *       #ASCON_AEAD_TAG_MIN_SECURE_LEN is recommended for security.
 * @returns number of bytes written into \p ciphertext. The value is in the
 *        interval [0, #ASCON_DOUBLE_RATE[, i.e. whatever remained in the buffer
 *        after the last update call.
 */
ASCON_API size_t
ascon_aead128a_encrypt_final(ascon_aead_ctx_t* ctx,
                             uint8_t* ciphertext,
                             uint8_t* tag,
                             size_t tag_len);

/**
 * Offline symmetric decryption using Ascon128a, which uses a double data rate
 * compared to Ascon128.
 *
 * Decrypts the data which is already available as a whole in a contiguous
 * buffer, validating any optional associated data in the process.
 * Provides the plaintext and the validity of the authentication tag as output.
 * The total plaintext length is equal to the total ciphertext length.
 *
 * In case of no associated data at all to be authenticated, set
 * \p assoc_data_len to 0. Iff that is the case, \p assoc_data can
 * be set to NULL.
 *
 * @image html decrypt.png
 *
 * @param[out] plaintext decrypted data with the same length as the
 *       ciphertext, thus \p ciphertext_len will be written in this buffer.
 *       This pointer may also point to the same location as \p ciphertext
 *       to decrypt the ciphertext in-place, sparing on memory instead
 *       of writing into a separate output buffer. Not NULL.
 * @param[in] key secret key of #ASCON_AEAD128a_KEY_LEN bytes. Not NULL.
 * @param[in] nonce public unique nonce of #ASCON_AEAD_NONCE_LEN bytes.
 * @param[in] assoc_data data to be validated with the same tag
 *        but not decrypted. Can be NULL iff \p assoc_data_len is 0.
 * @param[in] ciphertext data to be decrypted into \p plaintext.
 * @param[in] expected_tag Message Authentication Code (MAC, a.k.a. cryptographic tag,
 *       fingerprint), used to validate the integrity and authenticity of the
 *       associated data and ciphertext. Has \p tag_len bytes. Not NULL.
 * @param[in] assoc_data_len length of the data pointed by \p assoc_data in
 *        bytes. Can be 0.
 * @param[in] ciphertext_len length of the data pointed by \p ciphertext in
 *        bytes. Can be 0 (not recommended, see warning of
 *        ascon_aead128_encrypt()).
 * @param[in] expected_tag_len length of the \p tag to check in bytes. It should be
 *       the same length as generated during the encryption
 *       but it can be shorter (although it's not recommended).
 * @returns the answer to the question "is tha tag valid?", thus
 *        `true` (== #ASCON_TAG_OK) if the validation of the tag is correct,
 *        thus the associated data and ciphertext are intact and authentic.
 *        `false` (== #ASCON_TAG_INVALID) otherwise.
 */
ASCON_API bool
ascon_aead128a_decrypt(uint8_t* plaintext,
                       const uint8_t key[ASCON_AEAD128a_KEY_LEN],
                       const uint8_t nonce[ASCON_AEAD_NONCE_LEN],
                       const uint8_t* assoc_data,
                       const uint8_t* ciphertext,
                       const uint8_t* expected_tag,
                       size_t assoc_data_len,
                       size_t ciphertext_len,
                       size_t expected_tag_len);

/**
 * Online symmetric decryption using Ascon128a, feeding ciphertext and getting
 * plaintext.
 *
 * Feeds a chunk of ciphertext data to the decryption session after any
 * optional associated data has been processed. The ciphertext will be decrypted
 * and provided back in buffered chunks of #ASCON_RATE bytes.
 *
 * It will automatically finalise the absorption of any associated data,
 * so no new associated data could be processed after this function is called.
 *
 * The calling order for decryption is:
 * 1. ascon_aead128a_init() - once only
 * 2. ascon_aead128a_assoc_data_update() - 0 or more times
 * 3. ascon_aead128a_decrypt_update() - 0 or more times, see warning
 * 4. ascon_aead128a_decrypt_final() - once only
 *
 * @param[in, out] ctx the decryption context, handling the cipher state
 *       and buffering of incoming data to be processed. Not NULL.
 * @param[out] plaintext decrypted data, buffered into chunks.
 *       This function will write a multiple of #ASCON_DOUBLE_RATE bytes in the
 *       interval [0, \p ciphertext_len + #ASCON_DOUBLE_RATE[ into \p plaintext.
 *       The exact number of written bytes is indicated by the return value.
 *       This pointer may also point to the same location as \p ciphertext
 *       to decrypt the ciphertext in-place, sparing on memory instead
 *       of writing into a separate output buffer. Not NULL.
 * @param[in] ciphertext data to be decrypted into \p plaintext. All of the
 *       ciphertext will be processed, even if the function provides less than
 *       \p ciphertext_len output bytes. They are just buffered. Not NULL.
 * @param[in] ciphertext_len length of the data pointed by \p ciphertext in
 *        bytes. May be 0.
 * @returns number of bytes written into \p plaintext. The value is a multiple
 *        of #ASCON_DOUBLE_RATE in [0, \p ciphertext_len + #ASCON_DOUBLE_RATE[.
 */
ASCON_API size_t
ascon_aead128a_decrypt_update(ascon_aead_ctx_t* ctx,
                              uint8_t* plaintext,
                              const uint8_t* ciphertext,
                              size_t ciphertext_len);


/**
 * Online symmetric decryption using Ascon128a, finalisation and tag validation.
 *
 * Finalises the authenticated decryption by returning any remaining buffered
 * plaintext and the validity of the authentication tag.
 * The total plaintext length is equal to the total ciphertext length.
 *
 * It will securely erase the content of the \p ctx struct before returning.
 *
 * The calling order for decryption is:
 * 1. ascon_aead128a_init() - once only
 * 2. ascon_aead128a_assoc_data_update() - 0 or more times
 * 3. ascon_aead128a_decrypt_update() - 0 or more times, see warning
 * 4. ascon_aead128a_decrypt_final() - once only
 *
 * @warning
 * A copy of the secret key is kept in the \p ctx struct and securely erased
 * during the this function call. In case the decryption session is interrupted
 * and never finalised (this function is never called), clear the context with
 * ascon_aead_cleanup() to erase the key copy.
 *
 * @param[in, out] ctx the decryption context, handling the cipher
 *       state and buffering of incoming data to be processed. It will be erased
 *       securely before this function returns. Not NULL.
 * @param[out] plaintext trailing decrypted data still available in the
 *       buffer of the buffered updating. This function will write
 *       [0, #ASCON_DOUBLE_RATE[ bytes into \p plaintext.
 *       The exact number of written bytes is indicated by the return value.
 *       Not NULL.
 * @param[out] is_tag_valid the answer to the question "is the tag valid?", thus
 *        `true` (== #ASCON_TAG_OK) if the validation of the tag is correct,
 *        thus the associated data and ciphertext are intact and authentic.
 *        `false` (== #ASCON_TAG_INVALID) otherwise.
 * @param[in] expected_tag Message Authentication Code (MAC, a.k.a. cryptographic tag,
 *       fingerprint), used to validate the integrity and authenticity of the
 *       associated data and ciphertext. Has \p tag_len bytes. Not NULL.
 * @param[in] expected_tag_len length of the \p tag to check in bytes. It should be
 *       the same length as generated during the encryption
 *       but it can be shorter (although it's not recommended).
 * @returns number of bytes written into \p plaintext. The value is in the
 *        interval [0, #ASCON_DOUBLE_RATE[, i.e. whatever remained in the buffer
 *        after the last update call.
 */
ASCON_API size_t
ascon_aead128a_decrypt_final(ascon_aead_ctx_t* ctx,
                             uint8_t* plaintext,
                             bool* is_tag_valid,
                             const uint8_t* expected_tag,
                             size_t expected_tag_len);


/**
 * Offline symmetric encryption using Ascon80pq, which uses a larger key.
 *
 * Encrypts the data which is already available as a whole in a contiguous
 * buffer, authenticating any optional associated data in the process.
 * Provides the ciphertext and the authentication tag as output.
 *
 * In case of no associated data at all to be authenticated, set
 * \p assoc_data_len to 0. Iff that is the case, \p assoc_data can
 * be set to NULL.
 *
 * @image html encrypt.png
 *
 * @warning
 * The nonce **must be unique**, as the strength of the AEAD is based on
 * its uniqueness.
 *
 * @warning
 * Using the AEAD to just authenticate any associated data with no
 * plaintext to be encrypted is not recommended as the AEAD algorithm is not
 * designed for that. Instead use the Ascon hashing or xof functions in the
 * form `Hash(key || msg)`.
 *
 * @param[out] ciphertext encrypted data with the same length as the
 *       plaintext, thus \p plaintext_len will be written in this buffer.
 *       This pointer may also point to the same location as \p plaintext
 *       to encrypt the plaintext in-place, sparing on memory instead
 *       of writing into a separate output buffer. Not NULL.
 * @param[out] tag Message Authentication Code (MAC, a.k.a. cryptographic tag,
 *       fingerprint), used to validate the integrity and authenticity of the
 *       associated data and ciphertext. Has \p tag_len bytes. Not NULL.
 * @param[in] key secret key of #ASCON_AEAD80pq_KEY_LEN bytes. Not NULL.
 * @param[in] nonce public **unique** nonce of #ASCON_AEAD_NONCE_LEN bytes.
 * @param[in] assoc_data data to be authenticated with the same tag
 *        but not encrypted. Can be NULL iff \p assoc_data_len is 0.
 * @param[in] plaintext data to be encrypted into \p ciphertext.
 * @param[in] assoc_data_len length of the data pointed by \p assoc_data in
 *        bytes. Can be 0.
 * @param[in] plaintext_len length of the data pointed by \p plaintext in
 *        bytes. Can be 0 (not recommended, see warning).
 * @param[in] tag_len length of the tag to generate in bytes. At least
 *       #ASCON_AEAD_TAG_MIN_SECURE_LEN is recommended for security.
*/
ASCON_API void
ascon_aead80pq_encrypt(uint8_t* ciphertext,
                       uint8_t* tag,
                       const uint8_t key[ASCON_AEAD80pq_KEY_LEN],
                       const uint8_t nonce[ASCON_AEAD_NONCE_LEN],
                       const uint8_t* assoc_data,
                       const uint8_t* plaintext,
                       size_t assoc_data_len,
                       size_t plaintext_len,
                       size_t tag_len);


/**
 * Online symmetric encryption/decryption using Ascon80pq, initialisation -
 * note that a larger key is used compared to Ascon128 and Ascon128a.
 *
 * Prepares to start a new encryption or decryption session for plaintext or
 * ciphertext and associated data being provided one chunk at the time.
 *
 * The key and nonce are copied/absorbed into the internal state, so they can
 * be deleted from their original location after this function returns.
 *
 * The calling order for encryption/decryption is:
 * 1. ascon_aead80pq_init() - once only
 * 2. ascon_aead80pq_assoc_data_update() - 0 or more times
 * 3. ascon_aead80pq_encrypt_update() / ascon_aead80pq_decrypt_update() - 0 or
 *    more times, see warning
 * 4. ascon_aead80pq_encrypt_final() / ascon_aead80pq_encrypt_final() - once
 *    only
 *
 * @image html encrypt.png
 * @image html decrypt.png
 *
 * @warning
 * Using the AEAD to just authenticate any associated data with no
 * plaintext to be encrypted is not recommended as the AEAD algorithm is not
 * designed for that. Instead use the Ascon hashing or xof functions in the form
 * `Hash(key || msg)`.
 *
 * @warning
 * A copy of the secret key is kept in the \p ctx struct and securely erased
 * during the ascon_aead80pq_encrypt_final() or ascon_aead80pq_decrypt_final()
 * call. In case the encryption or decryption session is interrupted and never
 * finalised, clear the context with ascon_aead_cleanup() to erase the key copy.
 *
 * @warning
 * Do not mix Init-Update-Final functions across ciphers.
 *
 * @param[in, out] ctx the encryption/decryption context, handling the cipher
 *       state and buffering of incoming data to be processed. Not NULL.
 * @param[in] key secret key of #ASCON_AEAD80pq_KEY_LEN bytes. Not NULL
 * @param[in] nonce public unique nonce of #ASCON_AEAD_NONCE_LEN bytes. Not
 *       NULL.
 */
ASCON_API void
ascon_aead80pq_init(ascon_aead_ctx_t* ctx,
                    const uint8_t key[ASCON_AEAD80pq_KEY_LEN],
                    const uint8_t nonce[ASCON_AEAD_NONCE_LEN]);

/**
 * Online symmetric encryption/decryption using Ascon80pq, feeding associated
 * data.
 *
 * Feeds a chunk of associated data to the already initialised encryption
 * or decryption session. The data will be authenticated by the tag provided by
 * the final function, but not encrypted or decrypted.
 *
 * In case of no associated data at all to be authenticated/validated, this
 * function can either be either skipped completely or called (also many times)
 * with \p assoc_data_len set to 0. Iff that is the case, \p assoc_data can
 * be set to NULL.
 *
 * After calling ascon_aead80pq_encrypt_update() or
 * ascon_aead80pq_decrypt_update(), this function **must** not be used anymore
 * on the same context.
 *
 * The calling order for encryption/decryption is:
 * 1. ascon_aead80pq_init() - once only
 * 2. ascon_aead80pq_assoc_data_update() - 0 or more times
 * 3. ascon_aead80pq_encrypt_update() / ascon_aead80pq_decrypt_update() - 0 or
 *    more times, see warning
 * 4. ascon_aead80pq_encrypt_final() / ascon_aead80pq_encrypt_final() - once
 *    only
 *
 * @warning
 * Using the AEAD to just authenticate any associated data with no
 * plaintext to be encrypted is not recommended as the AEAD algorithm is not
 * designed for that. Instead use the Ascon hashing or xof functions in the form
 * `Hash(key || msg)`.
 *
 * @param[in, out] ctx the encryption/decryption context, handling the cipher
 *       state and buffering of incoming data to be processed. Not NULL.
 * @param[in] assoc_data data to be authenticated/validated with the same tag
 *        but not encrypted/decrypted. May be NULL iff \p assoc_data_len is 0.
 * @param[in] assoc_data_len length of the data pointed by \p assoc_data in
 *        bytes. May be 0.
 */
ASCON_API void
ascon_aead80pq_assoc_data_update(ascon_aead_ctx_t* ctx,
                                 const uint8_t* assoc_data,
                                 size_t assoc_data_len);

/**
 * Online symmetric encryption using Ascon80pq, feeding plaintext and getting
 * ciphertext.
 *
 * Feeds a chunk of plaintext data to the encryption session after any
 * optional associated data has been processed. The plaintext will be encrypted
 * and provided as ciphertext in buffered chunks of #ASCON_RATE bytes.
 *
 * It will automatically finalise the absorption of any associated data,
 * so no new associated data could be processed after this function is called.
 *
 * The calling order for encryption is:
 * 1. ascon_aead80pq_init() - once only
 * 2. ascon_aead80pq_assoc_data_update() - 0 or more times
 * 3. ascon_aead80pq_encrypt_update() - 0 or more times, see warning
 * 4. ascon_aead80pq_encrypt_final() - once only
 *
 * @warning
 * Using the AEAD to just authenticate any associated data with no
 * plaintext to be encrypted is not recommended as the AEAD algorithm is not
 * designed for that. Instead use the Ascon hashing or xof functions in the form
 * `Hash(key || msg)`.
 *
 * @param[in, out] ctx the encryption context, handling the cipher
 *       state and buffering of incoming data to be processed. Not NULL.
 * @param[out] ciphertext encrypted data, buffered into chunks.
 *       This function will write a multiple of #ASCON_RATE bytes in the
 *       interval [0, \p plaintext_len + #ASCON_RATE[ into \p ciphertext.
 *       The exact number of written bytes is indicated by the return value.
 *       This pointer may also point to the same location as \p plaintext
 *       to encrypt the plaintext in-place, sparing on memory instead
 *       of writing into a separate output buffer. Not NULL.
 * @param[in] plaintext data to be encrypted into \p ciphertext. All of the
 *       plaintext will be processed, even if the function provides less than
 *       \p plaintext_len output bytes. They are just buffered. Not NULL.
 * @param[in] plaintext_len length of the data pointed by \p plaintext in
 *        bytes. May be 0.
 * @returns number of bytes written into \p ciphertext. The value is a multiple
 *        of #ASCON_RATE in [0, \p plaintext_len + #ASCON_RATE[.
 */
ASCON_API size_t
ascon_aead80pq_encrypt_update(ascon_aead_ctx_t* ctx,
                              uint8_t* ciphertext,
                              const uint8_t* plaintext,
                              size_t plaintext_len);


/**
 * Online symmetric encryption using Ascon80pq, finalisation and tag generation.
 *
 * Finalises the authenticated encryption by returning any remaining buffered
 * ciphertext and the authentication tag. The total ciphertext length is
 * equal to the total plaintext length.
 *
 * It will securely erase the content of the \p ctx struct before returning.
 *
 * The calling order for encryption is:
 * 1. ascon_aead80pq_init() - once only
 * 2. ascon_aead80pq_assoc_data_update() - 0 or more times
 * 3. ascon_aead80pq_encrypt_update() - 0 or more times, see warning
 * 4. ascon_aead80pq_encrypt_final() - once only
 *
 * @warning
 * Using the AEAD to just authenticate any associated data with no
 * plaintext to be encrypted is not recommended as the AEAD algorithm is not
 * designed for that. Instead use the Ascon hashing or xof functions in the form
 * `Hash(key || msg)`.
 *
 * @warning
 * A copy of the secret key is kept in the \p ctx struct and securely erased
 * during the this function call. In case the encryption session is interrupted
 * and never finalised (this function is never called), clear the context with
 * ascon_aead_cleanup() to erase the key copy.
 *
 * @param[in, out] ctx the encryption context, handling the cipher
 *       state and buffering of incoming data to be processed. It will be erased
 *       securely before this function returns. Not NULL.
 * @param[out] ciphertext trailing encrypted data still available in the
 *       buffer of the buffered updating. This function will write
 *       [0, #ASCON_RATE[ bytes into \p ciphertext.
 *       The exact number of written bytes is indicated by the return value.
 *       Not NULL.
 * @param[out] tag Message Authentication Code (MAC, a.k.a. cryptographic tag,
 *       fingerprint), used to validate the integrity and authenticity of the
 *       associated data and ciphertext. Has \p tag_len bytes. Not NULL.
 * @param[in] tag_len length of the tag to generate in bytes. At least
 *       #ASCON_AEAD_TAG_MIN_SECURE_LEN is recommended for security.
 * @returns number of bytes written into \p ciphertext. The value is in the
 *        interval [0, #ASCON_RATE[, i.e. whatever remained in the buffer
 *        after the last update call.
 */
ASCON_API size_t
ascon_aead80pq_encrypt_final(ascon_aead_ctx_t* ctx,
                             uint8_t* ciphertext,
                             uint8_t* tag,
                             size_t tag_len);

/**
 * Offline symmetric decryption using Ascon80pq, which uses a larger key
 * compared to Ascon128.
 *
 * Decrypts the data which is already available as a whole in a contiguous
 * buffer, validating any optional associated data in the process.
 * Provides the plaintext and the validity of the authentication tag as output.
 * The total plaintext length is equal to the total ciphertext length.
 *
 * In case of no associated data at all to be authenticated, set
 * \p assoc_data_len to 0. Iff that is the case, \p assoc_data can
 * be set to NULL.
 *
 * @image html decrypt.png
 *
 * @param[out] plaintext decrypted data with the same length as the
 *       ciphertext, thus \p ciphertext_len will be written in this buffer.
 *       This pointer may also point to the same location as \p ciphertext
 *       to decrypt the ciphertext in-place, sparing on memory instead
 *       of writing into a separate output buffer. Not NULL.
 * @param[in] key secret key of #ASCON_AEAD80pq_KEY_LEN bytes. Not NULL.
 * @param[in] nonce public unique nonce of #ASCON_AEAD_NONCE_LEN bytes.
 * @param[in] assoc_data data to be validated with the same tag
 *        but not decrypted. Can be NULL iff \p assoc_data_len is 0.
 * @param[in] ciphertext data to be decrypted into \p plaintext.
 * @param[in] expected_tag Message Authentication Code (MAC, a.k.a. cryptographic tag,
 *       fingerprint), used to validate the integrity and authenticity of the
 *       associated data and ciphertext. Has \p tag_len bytes. Not NULL.
 * @param[in] assoc_data_len length of the data pointed by \p assoc_data in
 *        bytes. Can be 0.
 * @param[in] ciphertext_len length of the data pointed by \p ciphertext in
 *        bytes. Can be 0 (not recommended, see warning of
 *        ascon_aead128_encrypt()).
 * @param[in] expected_tag_len length of the \p tag to check in bytes. It should be
 *       the same length as generated during the encryption
 *       but it can be shorter (although it's not recommended).
 * @returns the answer to the question "is tha tag valid?", thus
 *        `true` (== #ASCON_TAG_OK) if the validation of the tag is correct,
 *        thus the associated data and ciphertext are intact and authentic.
 *        `false` (== #ASCON_TAG_INVALID) otherwise.
 */
ASCON_API bool
ascon_aead80pq_decrypt(uint8_t* plaintext,
                       const uint8_t key[ASCON_AEAD80pq_KEY_LEN],
                       const uint8_t nonce[ASCON_AEAD_NONCE_LEN],
                       const uint8_t* assoc_data,
                       const uint8_t* ciphertext,
                       const uint8_t* expected_tag,
                       size_t assoc_data_len,
                       size_t ciphertext_len,
                       size_t expected_tag_len);

/**
 * Online symmetric decryption using Ascon80pq, feeding ciphertext and getting
 * plaintext.
 *
 * Feeds a chunk of ciphertext data to the decryption session after any
 * optional associated data has been processed. The ciphertext will be decrypted
 * and provided back in buffered chunks of #ASCON_RATE bytes.
 *
 * It will automatically finalise the absorption of any associated data,
 * so no new associated data could be processed after this function is called.
 *
 * The calling order for decryption is:
 * 1. ascon_aead80pq_init() - once only
 * 2. ascon_aead80pq_assoc_data_update() - 0 or more times
 * 3. ascon_aead80pq_decrypt_update() - 0 or more times, see warning
 * 4. ascon_aead80pq_decrypt_final() - once only
 *
 * @param[in, out] ctx the decryption context, handling the cipher state
 *       and buffering of incoming data to be processed. Not NULL.
 * @param[out] plaintext decrypted data, buffered into chunks.
 *       This function will write a multiple of #ASCON_RATE bytes in the
 *       interval [0, \p ciphertext_len + #ASCON_RATE[ into \p plaintext.
 *       The exact number of written bytes is indicated by the return value.
 *       This pointer may also point to the same location as \p ciphertext
 *       to decrypt the ciphertext in-place, sparing on memory instead
 *       of writing into a separate output buffer. Not NULL.
 * @param[in] ciphertext data to be decrypted into \p plaintext. All of the
 *       ciphertext will be processed, even if the function provides less than
 *       \p ciphertext_len output bytes. They are just buffered. Not NULL.
 * @param[in] ciphertext_len length of the data pointed by \p ciphertext in
 *        bytes. May be 0.
 * @returns number of bytes written into \p plaintext. The value is a multiple
 *        of #ASCON_RATE in [0, \p ciphertext_len + #ASCON_RATE[.
 */
ASCON_API size_t
ascon_aead80pq_decrypt_update(ascon_aead_ctx_t* ctx,
                              uint8_t* plaintext,
                              const uint8_t* ciphertext,
                              size_t ciphertext_len);

/**
 * Online symmetric decryption using Ascon80pq, finalisation and tag validation.
 *
 * Finalises the authenticated decryption by returning any remaining buffered
 * plaintext and the validity of the authentication tag.
 * The total plaintext length is equal to the total ciphertext length.
 *
 * It will securely erase the content of the \p ctx struct before returning.
 *
 * The calling order for decryption is:
 * 1. ascon_aead80pq_init() - once only
 * 2. ascon_aead80pq_assoc_data_update() - 0 or more times
 * 3. ascon_aead80pq_decrypt_update() - 0 or more times, see warning
 * 4. ascon_aead80pq_decrypt_final() - once only
 *
 * @warning
 * A copy of the secret key is kept in the \p ctx struct and securely erased
 * during the this function call. In case the decryption session is interrupted
 * and never finalised (this function is never called), clear the context with
 * ascon_aead_cleanup() to erase the key copy.
 *
 * @param[in, out] ctx the decryption context, handling the cipher
 *       state and buffering of incoming data to be processed. It will be erased
 *       securely before this function returns. Not NULL.
 * @param[out] plaintext trailing decrypted data still available in the
 *       buffer of the buffered updating. This function will write
 *       [0, #ASCON_RATE[ bytes into \p plaintext.
 *       The exact number of written bytes is indicated by the return value.
 *       Not NULL.
 * @param[out] is_tag_valid the answer to the question "is the tag valid?", thus
 *        `true` (== #ASCON_TAG_OK) if the validation of the tag is correct,
 *        thus the associated data and ciphertext are intact and authentic.
 *        `false` (== #ASCON_TAG_INVALID) otherwise.
 * @param[in] expected_tag Message Authentication Code (MAC, a.k.a. cryptographic tag,
 *       fingerprint), used to validate the integrity and authenticity of the
 *       associated data and ciphertext. Has \p tag_len bytes. Not NULL.
 * @param[in] expected_tag_len length of the \p tag to check in bytes. It should be
 *       the same length as generated during the encryption
 *       but it can be shorter (although it's not recommended).
 * @returns number of bytes written into \p plaintext. The value is in the
 *        interval [0, #ASCON_RATE[, i.e. whatever remained in the buffer
 *        after the last update call.
 */
ASCON_API size_t
ascon_aead80pq_decrypt_final(ascon_aead_ctx_t* ctx,
                             uint8_t* plaintext,
                             bool* is_tag_valid,
                             const uint8_t* expected_tag,
                             size_t expected_tag_len);

/**
 * Offline Ascon Hash with fixed digest length.
 *
 * Hashes the data, which is already available as a whole in a contiguous
 * buffer, and provides the digest for it.
 *
 * @image html hash.png
 *
 * @remark
 * This function can be used for keyed hashing to generate a MAC by simply
 * prepending a secret key to the message, like `ascon_hash(key || msg)`. There
 * is **no need to build an HMAC** construct around it, as it does not suffer
 * from length-extension vulnerabilities.
 *
 * @param[out] digest fingerprint of the message, output of the hash function,
 *       of #ASCON_HASH_DIGEST_LEN bytes.
 * @param[in] data message fed into the hash function.
 * @param[in] data_len length of \p data in bytes.
 */
ASCON_API void
ascon_hash(uint8_t digest[ASCON_HASH_DIGEST_LEN],
           const uint8_t* data,
           size_t data_len);

/**
 * Offline Ascon Hash with fixed digest length, finalisation and digest
 * validation of the expected one.
 *
 * Hashes the data, which is already available as a whole in a contiguous
 * buffer, and provides the digest for it.
 *
 * @image html hash.png
 *
 * @remark
 * This function can be used for keyed hashing to generate a MAC by simply
 * prepending a secret key to the message, like `ascon_hash(key || msg)`. There
 * is **no need to build an HMAC** construct around it, as it does not suffer
 * from length-extension vulnerabilities.
 *
 * @param[in] expected_digest expected fingerprint of the message, output of
 *       the ascon_hash_final() or ascon_hash() function,
 *       of #ASCON_HASH_DIGEST_LEN bytes.
 *       This is the digest that comes with the message and will be compared
 *       with the internally-generated one by this function.
 * @param[in] data message fed into the hash function.
 * @param[in] data_len length of \p data in bytes.
 * @return the answer to the question "is the digest valid?", thus
 *        `true` (== #ASCON_TAG_OK) if the validation of the digest is correct,
 *        thus the message is intact (and authentic if a keyed hash was
 *        performed), `false` (== #ASCON_TAG_INVALID) otherwise.
 */
ASCON_API bool
ascon_hash_matches(const uint8_t expected_digest[ASCON_HASH_DIGEST_LEN],
                   const uint8_t* data,
                   size_t data_len);

/**
 * Online Ascon Hash with fixed digest length, initialisation.
 *
 * Prepares to start a new hashing session to get a digest of
 * #ASCON_HASH_DIGEST_LEN bytes.
 *
 * @image html hash.png
 *
 * @remark
 * This function can be used for keyed hashing to generate a MAC by simply
 * prepending a secret key to the message, like `ascon_hash(key || msg)`. There
 * is **no need to build an HMAC** construct around it, as it does not suffer
 * from length-extension vulnerabilities.
 *
 * @warning
 * Do not mix Init-Update-Final functions of Ascon-Hash and Ascon-XOF.
 *
 * @param[in, out] ctx the hashing context, handling the hash function state
 *       and buffering of incoming data to be processed. Not NULL.
 */
ASCON_API void
ascon_hash_init(ascon_hash_ctx_t* ctx);

/**
 * Online Ascon Hash with fixed digest length, feeding data to hash.
 *
 * Feeds a chunk of data to the already initialised hashing session.
 *
 * In case of no data at all to be hashed, this function can be called (also
 * many times) with \p data_len set to 0. Iff that is the case, \p data can be
 * set to NULL.
 *
 * @param[in, out] ctx the hashing context, handling the hash function state
 *       and buffering of incoming data to be processed. Not NULL.
 * @param[in] data bytes to be hashes. May be NULL iff \p data_len is 0.
 * @param[in] data_len length of the \p data pointed by in bytes. May be 0.
 */
ASCON_API void
ascon_hash_update(ascon_hash_ctx_t* ctx,
                  const uint8_t* data,
                  size_t data_len);

/**
 * Online Ascon Hash with fixed digest length, finalisation and digest
 * generation.
 *
 * Finalises the hashing by returning the digest of the message.
 *
 * @warning
 * In case the hashing session is interrupted and never finalised (this function
 * is never called), clear the context with ascon_hash_cleanup() to erase any
 * information about the hashed content, especially in case keyed hashing is
 * performed.
 *
 * @param[in, out] ctx the hashing context, handling the hash function state
 *       and buffering of incoming data to be processed. It will be erased
 *       securely before this function returns. Not NULL.
 * @param[out] digest fingerprint of the message, output of the hash function,
 *       of #ASCON_HASH_DIGEST_LEN bytes.
 */
ASCON_API void
ascon_hash_final(ascon_hash_ctx_t* ctx,
                 uint8_t digest[ASCON_HASH_DIGEST_LEN]);

/**
 * Online Ascon Hash with fixed digest length, finalisation and digest
 * validation of the expected one.
 *
 * @warning
 * In case the hashing session is interrupted and never finalised (this function
 * is never called), clear the context with ascon_hash_cleanup() to erase any
 * information about the hashed content, especially in case keyed hashing is
 * performed.
 *
 * @param[in, out] ctx the hashing context, handling the hash function state
 *       and buffering of incoming data to be processed. It will be erased
 *       securely before this function returns. Not NULL.
 * @param[in] expected_digest expected fingerprint of the message, output of
 *       the ascon_hash_final() or ascon_hash() function,
 *       of #ASCON_HASH_DIGEST_LEN bytes.
 *       This is the digest that comes with the message and will be compared
 *       with the internally-generated one by this function.
 * @return the answer to the question "is the digest valid?", thus
 *        `true` (== #ASCON_TAG_OK) if the validation of the digest is correct,
 *        thus the message is intact (and authentic if a keyed hash was
 *        performed), `false` (== #ASCON_TAG_INVALID) otherwise.
 */
ASCON_API bool
ascon_hash_final_matches(ascon_hash_ctx_t* ctx,
                         const uint8_t expected_digest[ASCON_HASH_DIGEST_LEN]);

/**
 * Offline Ascon Hash with custom digest length (eXtendable Output Function,
 * XOF).
 *
 * Hashes the data, which is already available as a whole in a contiguous
 * buffer, and provides the digest for it of the desired length.
 *
 * @image html hash.png
 *
 * @remark
 * This function can be used for keyed hashing to generate a MAC by simply
 * prepending a secret key to the message, like `ascon_hash_xof(key || msg)`.
 * There is **no need to build an HMAC** construct around it, as it does not
 * suffer from length-extension vulnerabilities.
 *
 * @warning
 * To have 128 bits of security against birthday attacks (collisions),
 * a digest length of at least 256 bits (32 bytes) is recommended. Against
 * quantum computers, the hash size should be double the amount of wanted
 * security bits.
 *
 * @param[out] digest fingerprint of the message, output of the hash function,
 *       of \p digest_len bytes.
 * @param[in] data message fed into the hash function.
 * @param[in] digest_len desired length of the \p digest in bytes.
 * @param[in] data_len length of \p data in bytes.
 */
ASCON_API void
ascon_hash_xof(uint8_t* digest,
               const uint8_t* data,
               size_t digest_len,
               size_t data_len);

/**
 * Offline Ascon Hash with custom digest length (eXtendable Output Function,
 * XOF) and validation of the expected one.
 *
 * Hashes the data, which is already available as a whole in a contiguous
 * buffer, and provides the digest for it of the desired length.
 *
 * @image html hash.png
 *
 * @remark
 * This function can be used for keyed hashing to generate a MAC by simply
 * prepending a secret key to the message, like `ascon_hash_xof(key || msg)`.
 * There is **no need to build an HMAC** construct around it, as it does not
 * suffer from length-extension vulnerabilities.
 *
 * @warning
 * To have 128 bits of security against birthday attacks (collisions),
 * a digest length of at least 256 bits (32 bytes) is recommended. Against
 * quantum computers, the hash size should be double the amount of wanted
 * security bits.
 *
 * @param[in] expected_digest expected fingerprint of the message, output of
 *       the ascon_hash_xof_final() or ascon_hash_xof() function,
 *       of \p expected_digest_len bytes.
 *       This is the digest that comes with the message and will be compared
 *       with the internally-generated one by this function.
 * @param[in] data message fed into the hash function.
 * @param[in] expected_digest_len desired length of the \p expected_digest
 *       in bytes.
 * @param[in] data_len length of \p data in bytes.
 * @return the answer to the question "is the digest valid?", thus
 *        `true` (== #ASCON_TAG_OK) if the validation of the digest is correct,
 *        thus the message is intact (and authentic if a keyed hash was
 *        performed), `false` (== #ASCON_TAG_INVALID) otherwise.
 */
ASCON_API bool
ascon_hash_xof_matches(const uint8_t* expected_digest,
                       const uint8_t* data,
                       size_t expected_digest_len,
                       size_t data_len);

/**
 * Online Ascon Hash with custom digest length (eXtendable Output Function,
 * XOF), initialisation.
 *
 * Prepares to start a new hashing session to get a digest of custom length.
 *
 * @image html encrypt.png
 *
 * @remark
 * This function can be used for keyed hashing to generate a MAC by simply
 * prepending a secret key to the message, like `ascon_hash_xof(key || msg)`.
 * There is **no need to build an HMAC** construct around it, as it does not
 * suffer from length-extension vulnerabilities.
 *
 * @warning
 * Do not mix Init-Update-Final functions of Ascon-Hash and Ascon-XOF.
 *
 * @param[in, out] ctx the hashing context, handling the hash function state
 *       and buffering of incoming data to be processed. Not NULL.
 */
ASCON_API void
ascon_hash_xof_init(ascon_hash_ctx_t* ctx);

/**
 * Online Ascon Hash with custom digest length (eXtendable Output Function,
 * XOF), feeding data to hash.
 *
 * Feeds a chunk of data to the already initialised hashing session.
 *
 * In case of no data at all to be hashed, this function can be called (also
 * many times) with \p data_len set to 0. Iff that is the case, \p data can be
 * set to NULL.
 *
 * @param[in, out] ctx the hashing context, handling the hash function state
 *       and buffering of incoming data to be processed. Not NULL.
 * @param[in] data bytes to be hashes. May be NULL iff \p data_len is 0.
 * @param[in] data_len length of the \p data pointed by in bytes. May be 0.
 */
ASCON_API void
ascon_hash_xof_update(ascon_hash_ctx_t* ctx,
                      const uint8_t* data,
                      size_t data_len);

/**
 * Online Ascon Hash with custom digest length (eXtendable Output Function,
 * XOF), finalisation and digest generation.
 *
 * Finalises the hashing by returning the digest of the message.
 *
 * @warning
 * To have 128 bits of security against birthday attacks (collisions),
 * a digest length of at least 256 bits (32 bytes) is recommended. Against
 * quantum computers, the hash size should be double the amount of wanted
 * security bits.
 *
 * @warning
 * In case the hashing session is interrupted and never finalised (this function
 * is never called), clear the context with ascon_hash_cleanup() to erase any
 * information about the hashed content, especially in case keyed hashing is
 * performed.
 *
 * @param[in, out] ctx the hashing context, handling the hash function state
 *       and buffering of incoming data to be processed. It will be erased
 *       securely before this function returns. Not NULL.
 * @param[out] digest fingerprint of the message, output of the hash function,
 *       of \p digest_size bytes.
 * @param[in] digest_len desired length of the \p digest in bytes.
 */
ASCON_API void
ascon_hash_xof_final(ascon_hash_ctx_t* ctx,
                     uint8_t* digest,
                     size_t digest_len);

/**
 * Online Ascon Hash with custom digest length (eXtendable Output Function,
 * XOF), finalisation and digest validation of the expected one.
 *
 * @param[in, out] ctx the hashing context, handling the hash function state
 *       and buffering of incoming data to be processed. It will be erased
 *       securely before this function returns. Not NULL.
 * @param[in] expected_digest expected fingerprint of the message, output of
 *       the ascon_hash_xof_final() or ascon_hash_xof() function,
 *       of \p expected_digest_len bytes.
 *       This is the digest that comes with the message and will be compared
 *       with the internally-generated one by this function.
 * @param[in] expected_digest_len desired length of the \p expected_digest in
 *       bytes.
 * @return the answer to the question "is the digest valid?", thus
 *        `true` (== #ASCON_TAG_OK) if the validation of the digest is correct,
 *        thus the message is intact (and authentic if a keyed hash was
 *        performed), `false` (== #ASCON_TAG_INVALID) otherwise.
 */
ASCON_API bool
ascon_hash_xof_final_matches(ascon_hash_ctx_t* ctx,
                             const uint8_t* expected_digest,
                             size_t expected_digest_len);

/**
 * Security cleanup of the hashing context, in case the online
 * processing is not completed to the end.
 *
 * Use this function only when something goes wrong between the calls of
 * online hashing or decryption and you never call the ascon_hash_final()
 * or ascon_hash_xof_final() functions (because these 2 functions perform the
 * cleanup automatically).
 *
 * This is to prevent any information to leak through the context in case an
 * hashing transaction is rolled back/abruptly terminated, especially parts of
 * a key (for keyed hashing) still buffered in the context.
 *
 * @param[in, out] ctx to erase.
 */
ASCON_API void
ascon_hash_cleanup(ascon_hash_ctx_t* ctx);

#ifdef __cplusplus
}
#endif

#endif  /* ASCON_H */
