aead-common.h 9.46 KB
/*
 * Copyright (C) 2020 Southern Storm Software, Pty Ltd.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#ifndef LWCRYPTO_AEAD_COMMON_H
#define LWCRYPTO_AEAD_COMMON_H

#include <stddef.h>

/**
 * \file aead-common.h
 * \brief Definitions that are common across AEAD schemes.
 *
 * AEAD stands for "Authenticated Encryption with Associated Data".
 * It is a standard API pattern for securely encrypting and
 * authenticating packets of data.
 */

#ifdef __cplusplus
extern "C" {
#endif

/**
 * \brief Encrypts and authenticates a packet with an AEAD scheme.
 *
 * \param c Buffer to receive the output.
 * \param clen On exit, set to the length of the output which includes
 * the ciphertext and the authentication tag.
 * \param m Buffer that contains the plaintext message to encrypt.
 * \param mlen Length of the plaintext message in bytes.
 * \param ad Buffer that contains associated data to authenticate
 * along with the packet but which does not need to be encrypted.
 * \param adlen Length of the associated data in bytes.
 * \param nsec Secret nonce - normally not used by AEAD schemes.
 * \param npub Points to the public nonce for the packet.
 * \param k Points to the key to use to encrypt the packet.
 *
 * \return 0 on success, or a negative value if there was an error in
 * the parameters.
 */
typedef int (*aead_cipher_encrypt_t)
    (unsigned char *c, unsigned long long *clen,
     const unsigned char *m, unsigned long long mlen,
     const unsigned char *ad, unsigned long long adlen,
     const unsigned char *nsec,
     const unsigned char *npub,
     const unsigned char *k);

/**
 * \brief Decrypts and authenticates a packet with an AEAD scheme.
 *
 * \param m Buffer to receive the plaintext message on output.
 * \param mlen Receives the length of the plaintext message on output.
 * \param nsec Secret nonce - normally not used by AEAD schemes.
 * \param c Buffer that contains the ciphertext and authentication
 * tag to decrypt.
 * \param clen Length of the input data in bytes, which includes the
 * ciphertext and the authentication tag.
 * \param ad Buffer that contains associated data to authenticate
 * along with the packet but which does not need to be encrypted.
 * \param adlen Length of the associated data in bytes.
 * \param npub Points to the public nonce for the packet.
 * \param k Points to the key to use to decrypt the packet.
 *
 * \return 0 on success, -1 if the authentication tag was incorrect,
 * or some other negative number if there was an error in the parameters.
 */
typedef int (*aead_cipher_decrypt_t)
    (unsigned char *m, unsigned long long *mlen,
     unsigned char *nsec,
     const unsigned char *c, unsigned long long clen,
     const unsigned char *ad, unsigned long long adlen,
     const unsigned char *npub,
     const unsigned char *k);

/**
 * \brief Hashes a block of input data.
 *
 * \param out Buffer to receive the hash output.
 * \param in Points to the input data to be hashed.
 * \param inlen Length of the input data in bytes.
 *
 * \return Returns zero on success or -1 if there was an error in the
 * parameters.
 */
typedef int (*aead_hash_t)
    (unsigned char *out, const unsigned char *in, unsigned long long inlen);

/**
 * \brief Initializes the state for a hashing operation.
 *
 * \param state Hash state to be initialized.
 */
typedef void (*aead_hash_init_t)(void *state);

/**
 * \brief Updates a hash state with more input data.
 *
 * \param state Hash state to be updated.
 * \param in Points to the input data to be incorporated into the state.
 * \param inlen Length of the input data to be incorporated into the state.
 */
typedef void (*aead_hash_update_t)
    (void *state, const unsigned char *in, unsigned long long inlen);

/**
 * \brief Returns the final hash value from a hashing operation.
 *
 * \param Hash state to be finalized.
 * \param out Points to the output buffer to receive the hash value.
 */
typedef void (*aead_hash_finalize_t)(void *state, unsigned char *out);

/**
 * \brief Aborbs more input data into an XOF state.
 *
 * \param state XOF state to be updated.
 * \param in Points to the input data to be absorbed into the state.
 * \param inlen Length of the input data to be absorbed into the state.
 *
 * \sa ascon_xof_init(), ascon_xof_squeeze()
 */
typedef void (*aead_xof_absorb_t)
    (void *state, const unsigned char *in, unsigned long long inlen);

/**
 * \brief Squeezes output data from an XOF state.
 *
 * \param state XOF state to squeeze the output data from.
 * \param out Points to the output buffer to receive the squeezed data.
 * \param outlen Number of bytes of data to squeeze out of the state.
 */
typedef void (*aead_xof_squeeze_t)
    (void *state, unsigned char *out, unsigned long long outlen);

/**
 * \brief No special AEAD features.
 */
#define AEAD_FLAG_NONE          0x0000

/**
 * \brief The natural byte order of the AEAD cipher is little-endian.
 *
 * If this flag is not present, then the natural byte order of the
 * AEAD cipher should be assumed to be big-endian.
 *
 * The natural byte order may be useful when formatting packet sequence
 * numbers as nonces.  The application needs to know whether the sequence
 * number should be packed into the leading or trailing bytes of the nonce.
 */
#define AEAD_FLAG_LITTLE_ENDIAN 0x0001

/**
 * \brief Meta-information about an AEAD cipher.
 */
typedef struct
{
    const char *name;               /**< Name of the cipher */
    unsigned key_len;               /**< Length of the key in bytes */
    unsigned nonce_len;             /**< Length of the nonce in bytes */
    unsigned tag_len;               /**< Length of the tag in bytes */
    unsigned flags;                 /**< Flags for extra features */
    aead_cipher_encrypt_t encrypt;  /**< AEAD encryption function */
    aead_cipher_decrypt_t decrypt;  /**< AEAD decryption function */

} aead_cipher_t;

/**
 * \brief Meta-information about a hash algorithm that is related to an AEAD.
 *
 * Regular hash algorithms should provide the "hash", "init", "update",
 * and "finalize" functions.  Extensible Output Functions (XOF's) should
 * proivde the "hash", "init", "absorb", and "squeeze" functions.
 */
typedef struct
{
    const char *name;           /**< Name of the hash algorithm */
    size_t state_size;          /**< Size of the incremental state structure */
    unsigned hash_len;          /**< Length of the hash in bytes */
    unsigned flags;             /**< Flags for extra features */
    aead_hash_t hash;           /**< All in one hashing function */
    aead_hash_init_t init;      /**< Incremental hash/XOF init function */
    aead_hash_update_t update;  /**< Incremental hash update function */
    aead_hash_finalize_t finalize; /**< Incremental hash finalize function */
    aead_xof_absorb_t absorb;   /**< Incremental XOF absorb function */
    aead_xof_squeeze_t squeeze; /**< Incremental XOF squeeze function */

} aead_hash_algorithm_t;

/**
 * \brief Check an authentication tag in constant time.
 *
 * \param plaintext Points to the plaintext data.
 * \param plaintext_len Length of the plaintext in bytes.
 * \param tag1 First tag to compare.
 * \param tag2 Second tag to compare.
 * \param tag_len Length of the tags in bytes.
 *
 * \return Returns -1 if the tag check failed or 0 if the check succeeded.
 *
 * If the tag check fails, then the \a plaintext will also be zeroed to
 * prevent it from being used accidentally by the application when the
 * ciphertext was invalid.
 */
int aead_check_tag
    (unsigned char *plaintext, unsigned long long plaintext_len,
     const unsigned char *tag1, const unsigned char *tag2,
     unsigned tag_len);

/**
 * \brief Check an authentication tag in constant time with a previous check.
 *
 * \param plaintext Points to the plaintext data.
 * \param plaintext_len Length of the plaintext in bytes.
 * \param tag1 First tag to compare.
 * \param tag2 Second tag to compare.
 * \param tag_len Length of the tags in bytes.
 * \param precheck Set to -1 if previous check succeeded or 0 if it failed.
 *
 * \return Returns -1 if the tag check failed or 0 if the check succeeded.
 *
 * If the tag check fails, then the \a plaintext will also be zeroed to
 * prevent it from being used accidentally by the application when the
 * ciphertext was invalid.
 *
 * This version can be used to incorporate other information about the
 * correctness of the plaintext into the final result.
 */
int aead_check_tag_precheck
    (unsigned char *plaintext, unsigned long long plaintext_len,
     const unsigned char *tag1, const unsigned char *tag2,
     unsigned tag_len, int precheck);

#ifdef __cplusplus
}
#endif

#endif