Commit b974ca1d by Alexandre Adomnicai Committed by Enrico Pozzobon

AVR implementations of Romulus and Skinny +

parent a3a77713
/*
* 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.
*/
#include "aead-common.h"
int aead_check_tag
(unsigned char *plaintext, unsigned long long plaintext_len,
const unsigned char *tag1, const unsigned char *tag2,
unsigned size)
{
/* Set "accum" to -1 if the tags match, or 0 if they don't match */
int accum = 0;
while (size > 0) {
accum |= (*tag1++ ^ *tag2++);
--size;
}
accum = (accum - 1) >> 8;
/* Destroy the plaintext if the tag match failed */
while (plaintext_len > 0) {
*plaintext++ &= accum;
--plaintext_len;
}
/* If "accum" is 0, return -1, otherwise return 0 */
return ~accum;
}
int aead_check_tag_precheck
(unsigned char *plaintext, unsigned long long plaintext_len,
const unsigned char *tag1, const unsigned char *tag2,
unsigned size, int precheck)
{
/* Set "accum" to -1 if the tags match, or 0 if they don't match */
int accum = 0;
while (size > 0) {
accum |= (*tag1++ ^ *tag2++);
--size;
}
accum = ((accum - 1) >> 8) & precheck;
/* Destroy the plaintext if the tag match failed */
while (plaintext_len > 0) {
*plaintext++ &= accum;
--plaintext_len;
}
/* If "accum" is 0, return -1, otherwise return 0 */
return ~accum;
}
/*
* 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
#define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 16
#define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1
#include "romulus.h"
int crypto_aead_encrypt
(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)
{
return romulus_m1_aead_encrypt
(c, clen, m, mlen, ad, adlen, nsec, npub, k);
}
int crypto_aead_decrypt
(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)
{
return romulus_m1_aead_decrypt
(m, mlen, nsec, c, clen, ad, adlen, npub, k);
}
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
* 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 LW_INTERNAL_SKINNY128_H
#define LW_INTERNAL_SKINNY128_H
/**
* \file internal-skinny128.h
* \brief SKINNY-128 block cipher family.
*
* References: https://eprint.iacr.org/2016/660.pdf,
* https://sites.google.com/site/skinnycipher/
*/
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \def SKINNY_128_SMALL_SCHEDULE
* \brief Defined to 1 to use the small key schedule version of SKINNY-128.
*/
#if defined(__AVR__)
#define SKINNY_128_SMALL_SCHEDULE 1
#else
#define SKINNY_128_SMALL_SCHEDULE 0
#endif
/**
* \brief Size of a block for SKINNY-128 block ciphers.
*/
#define SKINNY_128_BLOCK_SIZE 16
/**
* \brief Number of rounds for SKINNY-128-384.
*/
#define SKINNY_128_384_ROUNDS 56
/**
* \brief Structure of the key schedule for SKINNY-128-384.
*/
typedef struct
{
/** TK1 for the tweakable part of the key schedule */
uint8_t TK1[16];
#if SKINNY_128_SMALL_SCHEDULE
/** TK2 for the small key schedule */
uint8_t TK2[16];
/** TK3 for the small key schedule */
uint8_t TK3[16];
#else
/** Words of the full key schedule */
uint32_t k[SKINNY_128_384_ROUNDS * 2];
#endif
} skinny_128_384_key_schedule_t;
/**
* \brief Initializes the key schedule for SKINNY-128-384.
*
* \param ks Points to the key schedule to initialize.
* \param key Points to the key data.
*/
void skinny_128_384_init
(skinny_128_384_key_schedule_t *ks, const unsigned char key[48]);
/**
* \brief Encrypts a 128-bit block with SKINNY-128-384.
*
* \param ks Points to the SKINNY-128-384 key schedule.
* \param output Output buffer which must be at least 16 bytes in length.
* \param input Input buffer which must be at least 16 bytes in length.
*
* The \a input and \a output buffers can be the same buffer for
* in-place encryption.
*/
void skinny_128_384_encrypt
(const skinny_128_384_key_schedule_t *ks, unsigned char *output,
const unsigned char *input);
/**
* \brief Decrypts a 128-bit block with SKINNY-128-384.
*
* \param ks Points to the SKINNY-128-384 key schedule.
* \param output Output buffer which must be at least 16 bytes in length.
* \param input Input buffer which must be at least 16 bytes in length.
*
* The \a input and \a output buffers can be the same buffer for
* in-place encryption.
*/
void skinny_128_384_decrypt
(const skinny_128_384_key_schedule_t *ks, unsigned char *output,
const unsigned char *input);
/**
* \brief Encrypts a 128-bit block with SKINNY-128-384 and an explicitly
* provided TK2 value.
*
* \param ks Points to the SKINNY-128-384 key schedule.
* \param output Output buffer which must be at least 16 bytes in length.
* \param input Input buffer which must be at least 16 bytes in length.
* \param tk2 TK2 value that should be updated on the fly.
*
* The \a input and \a output buffers can be the same buffer for
* in-place encryption.
*
* This version is useful when both TK1 and TK2 change from block to block.
* When the key is initialized with skinny_128_384_init(), the TK2 part of
* the key value should be set to zero.
*
* \note Some versions of this function may modify the key schedule to
* copy tk2 into place.
*/
void skinny_128_384_encrypt_tk2
(skinny_128_384_key_schedule_t *ks, unsigned char *output,
const unsigned char *input, const unsigned char *tk2);
/**
* \brief Encrypts a 128-bit block with SKINNY-128-384 and a
* fully specified tweakey value.
*
* \param key Points to the 384-bit tweakey value.
* \param output Output buffer which must be at least 16 bytes in length.
* \param input Input buffer which must be at least 16 bytes in length.
*
* The \a input and \a output buffers can be the same buffer for
* in-place encryption.
*
* This version is useful when the entire tweakey changes from block to
* block. It is slower than the other versions of SKINNY-128-384 but
* more memory-efficient.
*/
void skinny_128_384_encrypt_tk_full
(const unsigned char key[48], unsigned char *output,
const unsigned char *input);
/**
* \brief Number of rounds for SKINNY-128-256.
*/
#define SKINNY_128_256_ROUNDS 48
/**
* \brief Structure of the key schedule for SKINNY-128-256.
*/
typedef struct
{
/** TK1 for the tweakable part of the key schedule */
uint8_t TK1[16];
#if SKINNY_128_SMALL_SCHEDULE
/** TK2 for the small key schedule */
uint8_t TK2[16];
#else
/** Words of the full key schedule */
uint32_t k[SKINNY_128_256_ROUNDS * 2];
#endif
} skinny_128_256_key_schedule_t;
/**
* \brief Initializes the key schedule for SKINNY-128-256.
*
* \param ks Points to the key schedule to initialize.
* \param key Points to the key data.
*/
void skinny_128_256_init
(skinny_128_256_key_schedule_t *ks, const unsigned char key[32]);
/**
* \brief Encrypts a 128-bit block with SKINNY-128-256.
*
* \param ks Points to the SKINNY-128-256 key schedule.
* \param output Output buffer which must be at least 16 bytes in length.
* \param input Input buffer which must be at least 16 bytes in length.
*
* The \a input and \a output buffers can be the same buffer for
* in-place encryption.
*/
void skinny_128_256_encrypt
(const skinny_128_256_key_schedule_t *ks, unsigned char *output,
const unsigned char *input);
/**
* \brief Decrypts a 128-bit block with SKINNY-128-256.
*
* \param ks Points to the SKINNY-128-256 key schedule.
* \param output Output buffer which must be at least 16 bytes in length.
* \param input Input buffer which must be at least 16 bytes in length.
*
* The \a input and \a output buffers can be the same buffer for
* in-place encryption.
*/
void skinny_128_256_decrypt
(const skinny_128_256_key_schedule_t *ks, unsigned char *output,
const unsigned char *input);
/**
* \brief Encrypts a 128-bit block with SKINNY-128-256 and a
* fully specified tweakey value.
*
* \param key Points to the 256-bit tweakey value.
* \param output Output buffer which must be at least 16 bytes in length.
* \param input Input buffer which must be at least 16 bytes in length.
*
* The \a input and \a output buffers can be the same buffer for
* in-place encryption.
*
* This version is useful when the entire tweakey changes from block to
* block. It is slower than the other versions of SKINNY-128-256 but
* more memory-efficient.
*/
void skinny_128_256_encrypt_tk_full
(const unsigned char key[32], unsigned char *output,
const unsigned char *input);
#ifdef __cplusplus
}
#endif
#endif
/*
* 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.
*/
#include "aead-common.h"
int aead_check_tag
(unsigned char *plaintext, unsigned long long plaintext_len,
const unsigned char *tag1, const unsigned char *tag2,
unsigned size)
{
/* Set "accum" to -1 if the tags match, or 0 if they don't match */
int accum = 0;
while (size > 0) {
accum |= (*tag1++ ^ *tag2++);
--size;
}
accum = (accum - 1) >> 8;
/* Destroy the plaintext if the tag match failed */
while (plaintext_len > 0) {
*plaintext++ &= accum;
--plaintext_len;
}
/* If "accum" is 0, return -1, otherwise return 0 */
return ~accum;
}
int aead_check_tag_precheck
(unsigned char *plaintext, unsigned long long plaintext_len,
const unsigned char *tag1, const unsigned char *tag2,
unsigned size, int precheck)
{
/* Set "accum" to -1 if the tags match, or 0 if they don't match */
int accum = 0;
while (size > 0) {
accum |= (*tag1++ ^ *tag2++);
--size;
}
accum = ((accum - 1) >> 8) & precheck;
/* Destroy the plaintext if the tag match failed */
while (plaintext_len > 0) {
*plaintext++ &= accum;
--plaintext_len;
}
/* If "accum" is 0, return -1, otherwise return 0 */
return ~accum;
}
/*
* 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
#define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 16
#define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1
#include "romulus.h"
int crypto_aead_encrypt
(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)
{
return romulus_n1_aead_encrypt
(c, clen, m, mlen, ad, adlen, nsec, npub, k);
}
int crypto_aead_decrypt
(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)
{
return romulus_n1_aead_decrypt
(m, mlen, nsec, c, clen, ad, adlen, npub, k);
}
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
* 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 LW_INTERNAL_SKINNY128_H
#define LW_INTERNAL_SKINNY128_H
/**
* \file internal-skinny128.h
* \brief SKINNY-128 block cipher family.
*
* References: https://eprint.iacr.org/2016/660.pdf,
* https://sites.google.com/site/skinnycipher/
*/
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \def SKINNY_128_SMALL_SCHEDULE
* \brief Defined to 1 to use the small key schedule version of SKINNY-128.
*/
#if defined(__AVR__)
#define SKINNY_128_SMALL_SCHEDULE 1
#else
#define SKINNY_128_SMALL_SCHEDULE 0
#endif
/**
* \brief Size of a block for SKINNY-128 block ciphers.
*/
#define SKINNY_128_BLOCK_SIZE 16
/**
* \brief Number of rounds for SKINNY-128-384.
*/
#define SKINNY_128_384_ROUNDS 56
/**
* \brief Structure of the key schedule for SKINNY-128-384.
*/
typedef struct
{
/** TK1 for the tweakable part of the key schedule */
uint8_t TK1[16];
#if SKINNY_128_SMALL_SCHEDULE
/** TK2 for the small key schedule */
uint8_t TK2[16];
/** TK3 for the small key schedule */
uint8_t TK3[16];
#else
/** Words of the full key schedule */
uint32_t k[SKINNY_128_384_ROUNDS * 2];
#endif
} skinny_128_384_key_schedule_t;
/**
* \brief Initializes the key schedule for SKINNY-128-384.
*
* \param ks Points to the key schedule to initialize.
* \param key Points to the key data.
*/
void skinny_128_384_init
(skinny_128_384_key_schedule_t *ks, const unsigned char key[48]);
/**
* \brief Encrypts a 128-bit block with SKINNY-128-384.
*
* \param ks Points to the SKINNY-128-384 key schedule.
* \param output Output buffer which must be at least 16 bytes in length.
* \param input Input buffer which must be at least 16 bytes in length.
*
* The \a input and \a output buffers can be the same buffer for
* in-place encryption.
*/
void skinny_128_384_encrypt
(const skinny_128_384_key_schedule_t *ks, unsigned char *output,
const unsigned char *input);
/**
* \brief Decrypts a 128-bit block with SKINNY-128-384.
*
* \param ks Points to the SKINNY-128-384 key schedule.
* \param output Output buffer which must be at least 16 bytes in length.
* \param input Input buffer which must be at least 16 bytes in length.
*
* The \a input and \a output buffers can be the same buffer for
* in-place encryption.
*/
void skinny_128_384_decrypt
(const skinny_128_384_key_schedule_t *ks, unsigned char *output,
const unsigned char *input);
/**
* \brief Encrypts a 128-bit block with SKINNY-128-384 and an explicitly
* provided TK2 value.
*
* \param ks Points to the SKINNY-128-384 key schedule.
* \param output Output buffer which must be at least 16 bytes in length.
* \param input Input buffer which must be at least 16 bytes in length.
* \param tk2 TK2 value that should be updated on the fly.
*
* The \a input and \a output buffers can be the same buffer for
* in-place encryption.
*
* This version is useful when both TK1 and TK2 change from block to block.
* When the key is initialized with skinny_128_384_init(), the TK2 part of
* the key value should be set to zero.
*
* \note Some versions of this function may modify the key schedule to
* copy tk2 into place.
*/
void skinny_128_384_encrypt_tk2
(skinny_128_384_key_schedule_t *ks, unsigned char *output,
const unsigned char *input, const unsigned char *tk2);
/**
* \brief Encrypts a 128-bit block with SKINNY-128-384 and a
* fully specified tweakey value.
*
* \param key Points to the 384-bit tweakey value.
* \param output Output buffer which must be at least 16 bytes in length.
* \param input Input buffer which must be at least 16 bytes in length.
*
* The \a input and \a output buffers can be the same buffer for
* in-place encryption.
*
* This version is useful when the entire tweakey changes from block to
* block. It is slower than the other versions of SKINNY-128-384 but
* more memory-efficient.
*/
void skinny_128_384_encrypt_tk_full
(const unsigned char key[48], unsigned char *output,
const unsigned char *input);
/**
* \brief Number of rounds for SKINNY-128-256.
*/
#define SKINNY_128_256_ROUNDS 48
/**
* \brief Structure of the key schedule for SKINNY-128-256.
*/
typedef struct
{
/** TK1 for the tweakable part of the key schedule */
uint8_t TK1[16];
#if SKINNY_128_SMALL_SCHEDULE
/** TK2 for the small key schedule */
uint8_t TK2[16];
#else
/** Words of the full key schedule */
uint32_t k[SKINNY_128_256_ROUNDS * 2];
#endif
} skinny_128_256_key_schedule_t;
/**
* \brief Initializes the key schedule for SKINNY-128-256.
*
* \param ks Points to the key schedule to initialize.
* \param key Points to the key data.
*/
void skinny_128_256_init
(skinny_128_256_key_schedule_t *ks, const unsigned char key[32]);
/**
* \brief Encrypts a 128-bit block with SKINNY-128-256.
*
* \param ks Points to the SKINNY-128-256 key schedule.
* \param output Output buffer which must be at least 16 bytes in length.
* \param input Input buffer which must be at least 16 bytes in length.
*
* The \a input and \a output buffers can be the same buffer for
* in-place encryption.
*/
void skinny_128_256_encrypt
(const skinny_128_256_key_schedule_t *ks, unsigned char *output,
const unsigned char *input);
/**
* \brief Decrypts a 128-bit block with SKINNY-128-256.
*
* \param ks Points to the SKINNY-128-256 key schedule.
* \param output Output buffer which must be at least 16 bytes in length.
* \param input Input buffer which must be at least 16 bytes in length.
*
* The \a input and \a output buffers can be the same buffer for
* in-place encryption.
*/
void skinny_128_256_decrypt
(const skinny_128_256_key_schedule_t *ks, unsigned char *output,
const unsigned char *input);
/**
* \brief Encrypts a 128-bit block with SKINNY-128-256 and a
* fully specified tweakey value.
*
* \param key Points to the 256-bit tweakey value.
* \param output Output buffer which must be at least 16 bytes in length.
* \param input Input buffer which must be at least 16 bytes in length.
*
* The \a input and \a output buffers can be the same buffer for
* in-place encryption.
*
* This version is useful when the entire tweakey changes from block to
* block. It is slower than the other versions of SKINNY-128-256 but
* more memory-efficient.
*/
void skinny_128_256_encrypt_tk_full
(const unsigned char key[32], unsigned char *output,
const unsigned char *input);
#ifdef __cplusplus
}
#endif
#endif
/*
* 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.
*/
#include "aead-common.h"
int aead_check_tag
(unsigned char *plaintext, unsigned long long plaintext_len,
const unsigned char *tag1, const unsigned char *tag2,
unsigned size)
{
/* Set "accum" to -1 if the tags match, or 0 if they don't match */
int accum = 0;
while (size > 0) {
accum |= (*tag1++ ^ *tag2++);
--size;
}
accum = (accum - 1) >> 8;
/* Destroy the plaintext if the tag match failed */
while (plaintext_len > 0) {
*plaintext++ &= accum;
--plaintext_len;
}
/* If "accum" is 0, return -1, otherwise return 0 */
return ~accum;
}
int aead_check_tag_precheck
(unsigned char *plaintext, unsigned long long plaintext_len,
const unsigned char *tag1, const unsigned char *tag2,
unsigned size, int precheck)
{
/* Set "accum" to -1 if the tags match, or 0 if they don't match */
int accum = 0;
while (size > 0) {
accum |= (*tag1++ ^ *tag2++);
--size;
}
accum = ((accum - 1) >> 8) & precheck;
/* Destroy the plaintext if the tag match failed */
while (plaintext_len > 0) {
*plaintext++ &= accum;
--plaintext_len;
}
/* If "accum" is 0, return -1, otherwise return 0 */
return ~accum;
}
/*
* 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
#define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 16
#define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1
#include "skinny-aead.h"
int crypto_aead_encrypt
(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)
{
return skinny_aead_m1_encrypt
(c, clen, m, mlen, ad, adlen, nsec, npub, k);
}
int crypto_aead_decrypt
(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)
{
return skinny_aead_m1_decrypt
(m, mlen, nsec, c, clen, ad, adlen, npub, k);
}
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
* 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 LW_INTERNAL_SKINNY128_H
#define LW_INTERNAL_SKINNY128_H
/**
* \file internal-skinny128.h
* \brief SKINNY-128 block cipher family.
*
* References: https://eprint.iacr.org/2016/660.pdf,
* https://sites.google.com/site/skinnycipher/
*/
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \def SKINNY_128_SMALL_SCHEDULE
* \brief Defined to 1 to use the small key schedule version of SKINNY-128.
*/
#if defined(__AVR__)
#define SKINNY_128_SMALL_SCHEDULE 1
#else
#define SKINNY_128_SMALL_SCHEDULE 0
#endif
/**
* \brief Size of a block for SKINNY-128 block ciphers.
*/
#define SKINNY_128_BLOCK_SIZE 16
/**
* \brief Number of rounds for SKINNY-128-384.
*/
#define SKINNY_128_384_ROUNDS 56
/**
* \brief Structure of the key schedule for SKINNY-128-384.
*/
typedef struct
{
/** TK1 for the tweakable part of the key schedule */
uint8_t TK1[16];
#if SKINNY_128_SMALL_SCHEDULE
/** TK2 for the small key schedule */
uint8_t TK2[16];
/** TK3 for the small key schedule */
uint8_t TK3[16];
#else
/** Words of the full key schedule */
uint32_t k[SKINNY_128_384_ROUNDS * 2];
#endif
} skinny_128_384_key_schedule_t;
/**
* \brief Initializes the key schedule for SKINNY-128-384.
*
* \param ks Points to the key schedule to initialize.
* \param key Points to the key data.
*/
void skinny_128_384_init
(skinny_128_384_key_schedule_t *ks, const unsigned char key[48]);
/**
* \brief Encrypts a 128-bit block with SKINNY-128-384.
*
* \param ks Points to the SKINNY-128-384 key schedule.
* \param output Output buffer which must be at least 16 bytes in length.
* \param input Input buffer which must be at least 16 bytes in length.
*
* The \a input and \a output buffers can be the same buffer for
* in-place encryption.
*/
void skinny_128_384_encrypt
(const skinny_128_384_key_schedule_t *ks, unsigned char *output,
const unsigned char *input);
/**
* \brief Decrypts a 128-bit block with SKINNY-128-384.
*
* \param ks Points to the SKINNY-128-384 key schedule.
* \param output Output buffer which must be at least 16 bytes in length.
* \param input Input buffer which must be at least 16 bytes in length.
*
* The \a input and \a output buffers can be the same buffer for
* in-place encryption.
*/
void skinny_128_384_decrypt
(const skinny_128_384_key_schedule_t *ks, unsigned char *output,
const unsigned char *input);
/**
* \brief Encrypts a 128-bit block with SKINNY-128-384 and an explicitly
* provided TK2 value.
*
* \param ks Points to the SKINNY-128-384 key schedule.
* \param output Output buffer which must be at least 16 bytes in length.
* \param input Input buffer which must be at least 16 bytes in length.
* \param tk2 TK2 value that should be updated on the fly.
*
* The \a input and \a output buffers can be the same buffer for
* in-place encryption.
*
* This version is useful when both TK1 and TK2 change from block to block.
* When the key is initialized with skinny_128_384_init(), the TK2 part of
* the key value should be set to zero.
*
* \note Some versions of this function may modify the key schedule to
* copy tk2 into place.
*/
void skinny_128_384_encrypt_tk2
(skinny_128_384_key_schedule_t *ks, unsigned char *output,
const unsigned char *input, const unsigned char *tk2);
/**
* \brief Encrypts a 128-bit block with SKINNY-128-384 and a
* fully specified tweakey value.
*
* \param key Points to the 384-bit tweakey value.
* \param output Output buffer which must be at least 16 bytes in length.
* \param input Input buffer which must be at least 16 bytes in length.
*
* The \a input and \a output buffers can be the same buffer for
* in-place encryption.
*
* This version is useful when the entire tweakey changes from block to
* block. It is slower than the other versions of SKINNY-128-384 but
* more memory-efficient.
*/
void skinny_128_384_encrypt_tk_full
(const unsigned char key[48], unsigned char *output,
const unsigned char *input);
/**
* \brief Number of rounds for SKINNY-128-256.
*/
#define SKINNY_128_256_ROUNDS 48
/**
* \brief Structure of the key schedule for SKINNY-128-256.
*/
typedef struct
{
/** TK1 for the tweakable part of the key schedule */
uint8_t TK1[16];
#if SKINNY_128_SMALL_SCHEDULE
/** TK2 for the small key schedule */
uint8_t TK2[16];
#else
/** Words of the full key schedule */
uint32_t k[SKINNY_128_256_ROUNDS * 2];
#endif
} skinny_128_256_key_schedule_t;
/**
* \brief Initializes the key schedule for SKINNY-128-256.
*
* \param ks Points to the key schedule to initialize.
* \param key Points to the key data.
*/
void skinny_128_256_init
(skinny_128_256_key_schedule_t *ks, const unsigned char key[32]);
/**
* \brief Encrypts a 128-bit block with SKINNY-128-256.
*
* \param ks Points to the SKINNY-128-256 key schedule.
* \param output Output buffer which must be at least 16 bytes in length.
* \param input Input buffer which must be at least 16 bytes in length.
*
* The \a input and \a output buffers can be the same buffer for
* in-place encryption.
*/
void skinny_128_256_encrypt
(const skinny_128_256_key_schedule_t *ks, unsigned char *output,
const unsigned char *input);
/**
* \brief Decrypts a 128-bit block with SKINNY-128-256.
*
* \param ks Points to the SKINNY-128-256 key schedule.
* \param output Output buffer which must be at least 16 bytes in length.
* \param input Input buffer which must be at least 16 bytes in length.
*
* The \a input and \a output buffers can be the same buffer for
* in-place encryption.
*/
void skinny_128_256_decrypt
(const skinny_128_256_key_schedule_t *ks, unsigned char *output,
const unsigned char *input);
/**
* \brief Encrypts a 128-bit block with SKINNY-128-256 and a
* fully specified tweakey value.
*
* \param key Points to the 256-bit tweakey value.
* \param output Output buffer which must be at least 16 bytes in length.
* \param input Input buffer which must be at least 16 bytes in length.
*
* The \a input and \a output buffers can be the same buffer for
* in-place encryption.
*
* This version is useful when the entire tweakey changes from block to
* block. It is slower than the other versions of SKINNY-128-256 but
* more memory-efficient.
*/
void skinny_128_256_encrypt_tk_full
(const unsigned char key[32], unsigned char *output,
const unsigned char *input);
#ifdef __cplusplus
}
#endif
#endif
/*
* 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.
*/
#include "skinny-hash.h"
#include "internal-skinny128.h"
#include "internal-util.h"
#include <string.h>
aead_hash_algorithm_t const skinny_tk3_hash_algorithm = {
"SKINNY-tk3-HASH",
sizeof(int),
SKINNY_HASH_SIZE,
AEAD_FLAG_NONE,
skinny_tk3_hash,
(aead_hash_init_t)0,
(aead_hash_update_t)0,
(aead_hash_finalize_t)0,
(aead_xof_absorb_t)0,
(aead_xof_squeeze_t)0
};
aead_hash_algorithm_t const skinny_tk2_hash_algorithm = {
"SKINNY-tk2-HASH",
sizeof(int),
SKINNY_HASH_SIZE,
AEAD_FLAG_NONE,
skinny_tk2_hash,
(aead_hash_init_t)0,
(aead_hash_update_t)0,
(aead_hash_finalize_t)0,
(aead_xof_absorb_t)0,
(aead_xof_squeeze_t)0
};
/**
* \brief Size of the permutation state for SKINNY-tk3-HASH.
*/
#define SKINNY_TK3_STATE_SIZE 48
/**
* \brief Size of the permutation state for SKINNY-tk2-HASH.
*/
#define SKINNY_TK2_STATE_SIZE 32
/**
* \brief Rate of absorbing data for SKINNY-tk3-HASH.
*/
#define SKINNY_TK3_HASH_RATE 16
/**
* \brief Rate of absorbing data for SKINNY-tk2-HASH.
*/
#define SKINNY_TK2_HASH_RATE 4
/**
* \brief Input block that is encrypted with the state for each
* block permutation of SKINNY-tk3-HASH or SKINNY-tk2-HASH.
*/
static unsigned char const skinny_hash_block[48] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/**
* \brief Permutes the internal state for SKINNY-tk3-HASH.
*
* \param state The state to be permuted.
*/
static void skinny_tk3_permute(unsigned char state[SKINNY_TK3_STATE_SIZE])
{
unsigned char temp[SKINNY_TK3_STATE_SIZE];
skinny_128_384_encrypt_tk_full(state, temp, skinny_hash_block);
skinny_128_384_encrypt_tk_full(state, temp + 16, skinny_hash_block + 16);
skinny_128_384_encrypt_tk_full(state, temp + 32, skinny_hash_block + 32);
memcpy(state, temp, SKINNY_TK3_STATE_SIZE);
}
/**
* \brief Permutes the internal state for SKINNY-tk2-HASH.
*
* \param state The state to be permuted.
*/
static void skinny_tk2_permute(unsigned char state[SKINNY_TK2_STATE_SIZE])
{
unsigned char temp[SKINNY_TK2_STATE_SIZE];
skinny_128_256_encrypt_tk_full(state, temp, skinny_hash_block);
skinny_128_256_encrypt_tk_full(state, temp + 16, skinny_hash_block + 16);
memcpy(state, temp, SKINNY_TK2_STATE_SIZE);
}
int skinny_tk3_hash
(unsigned char *out, const unsigned char *in, unsigned long long inlen)
{
unsigned char state[SKINNY_TK3_STATE_SIZE];
unsigned temp;
/* Initialize the hash state */
memset(state, 0, sizeof(state));
state[SKINNY_TK3_HASH_RATE] = 0x80;
/* Process as many full blocks as possible */
while (inlen >= SKINNY_TK3_HASH_RATE) {
lw_xor_block(state, in, SKINNY_TK3_HASH_RATE);
skinny_tk3_permute(state);
in += SKINNY_TK3_HASH_RATE;
inlen -= SKINNY_TK3_HASH_RATE;
}
/* Pad and process the last block */
temp = (unsigned)inlen;
lw_xor_block(state, in, temp);
state[temp] ^= 0x80; /* padding */
skinny_tk3_permute(state);
/* Generate the hash output */
memcpy(out, state, 16);
skinny_tk3_permute(state);
memcpy(out + 16, state, 16);
return 0;
}
int skinny_tk2_hash
(unsigned char *out, const unsigned char *in, unsigned long long inlen)
{
unsigned char state[SKINNY_TK2_STATE_SIZE];
unsigned temp;
/* Initialize the hash state */
memset(state, 0, sizeof(state));
state[SKINNY_TK2_HASH_RATE] = 0x80;
/* Process as many full blocks as possible */
while (inlen >= SKINNY_TK2_HASH_RATE) {
lw_xor_block(state, in, SKINNY_TK2_HASH_RATE);
skinny_tk2_permute(state);
in += SKINNY_TK2_HASH_RATE;
inlen -= SKINNY_TK2_HASH_RATE;
}
/* Pad and process the last block */
temp = (unsigned)inlen;
lw_xor_block(state, in, temp);
state[temp] ^= 0x80; /* padding */
skinny_tk2_permute(state);
/* Generate the hash output */
memcpy(out, state, 16);
skinny_tk2_permute(state);
memcpy(out + 16, state, 16);
return 0;
}
/*
* 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_SKINNY_HASH_H
#define LWCRYPTO_SKINNY_HASH_H
#include "aead-common.h"
/**
* \file skinny-hash.h
* \brief Hash algorithms based on the SKINNY block cipher.
*
* The SKINNY-AEAD family includes two hash algorithms:
*
* \li SKINNY-tk3-HASH with a 256-bit hash output, based around the
* SKINNY-128-384 tweakable block cipher. This is the primary hashing
* member of the family.
* \li SKINNY-tk2-HASH with a 256-bit hash output, based around the
* SKINNY-128-256 tweakable block cipher.
*
* References: https://sites.google.com/site/skinnycipher/home
*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Size of the hash output for SKINNY-tk3-HASH and SKINNY-tk2-HASH.
*/
#define SKINNY_HASH_SIZE 32
/**
* \brief Meta-information block for the SKINNY-tk3-HASH algorithm.
*/
extern aead_hash_algorithm_t const skinny_tk3_hash_algorithm;
/**
* \brief Meta-information block for the SKINNY-tk2-HASH algorithm.
*/
extern aead_hash_algorithm_t const skinny_tk2_hash_algorithm;
/**
* \brief Hashes a block of input data with SKINNY-tk3-HASH to
* generate a hash value.
*
* \param out Buffer to receive the hash output which must be at least
* SKINNY_HASH_SIZE bytes in length.
* \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.
*/
int skinny_tk3_hash
(unsigned char *out, const unsigned char *in, unsigned long long inlen);
/**
* \brief Hashes a block of input data with SKINNY-tk2-HASH to
* generate a hash value.
*
* \param out Buffer to receive the hash output which must be at least
* SKINNY_HASH_SIZE bytes in length.
* \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.
*/
int skinny_tk2_hash
(unsigned char *out, const unsigned char *in, unsigned long long inlen);
#ifdef __cplusplus
}
#endif
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment